Odczytaj dane z SqlDataReader


157

Mam bazę danych SQL Server 2008 i pracuję nad nią na zapleczu. Pracuję na asp.net/C#

SqlDataReader rdr = cmd.ExecuteReader();  
while (rdr.Read())  
{              
   //how do I read strings here????  
}  

Wiem, że czytelnik ma wartości. Moje polecenie SQL polega na wybraniu tylko jednej kolumny z tabeli. Kolumna zawiera TYLKO ciągi. Chcę czytać ciągi (wiersze) w czytniku jeden po drugim. Jak mam to zrobic?

Odpowiedzi:


154
using(SqlDataReader rdr = cmd.ExecuteReader())
{
    while (rdr.Read())
    {
        var myString = rdr.GetString(0); //The 0 stands for "the 0'th column", so the first column of the result.
        // Do somthing with this rows string, for example to put them in to a list
        listDeclaredElsewhere.Add(myString);
    }
}

106
string col1Value = rdr["ColumnOneName"].ToString();

lub

string col1Value = rdr[0].ToString();

To są objects, więc musisz je rzucić lub .ToString().


3
operator [] zwraca obiekt, będziesz musiał rzucić go jako łańcuch.
Scott Chamberlain

Jeśli używasz indeksów, takich jak reader.GetString (0), użyje pierwszej kolumny wybranej w zapytaniu lub pierwszej kolumny tabeli. Mam tabelę z 3 kolumnami w kolejności: ID, Dir, Email. Moje polecenie wybiera katalog i e-mail. Czy reader.GetStrting (0) pobierze katalog lub identyfikator? Czy indeksy są oparte na samej tabeli na serwerze SQL, czy na zapytaniu wykonanym w celu wybrania kolumn z tabeli?
shenk

1
@shenk Indeksy są oparte na kolejności wybranych parametrów. Tak czy inaczej, lepiej będzie, jeśli użyjesz nazw kolumn lub aliasów (tj. Rdr ["ID"] w przeciwieństwie do rdr [0])
Mark Avenius

1
@MarkAvenius było tak, że indeksowanie za pomocą liczb porządkowych poprawiło wydajność w porównaniu z nazwami kolumn / aliasami - nie jestem pewien, czy tak jest
BaltoStar

3
@BaltoStar to interesujące; Nie byłem tego świadomy. Jednak w zależności od różnicy w wydajności (zwłaszcza w porównaniu z przesyłaniem danych przez sieć, w oparciu o twoją aplikację), ogólnie powiedziałbym, że czytelność i łatwość konserwacji nazw kolumn byłaby lepsza od jakiejkolwiek marginalnej poprawy wydajności. Dzięki!
Mark Avenius,

36

Wpisz nazwę kolumny, która zacznie zwracana z bazy danych, gdzie "ColumnName"jest. Jeśli jest to ciąg, możesz użyć .ToString(). Jeśli jest to inny typ, musisz go przekonwertować za pomocą System.Convert.

SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
    string column = rdr["ColumnName"].ToString();
    int columnValue = Convert.ToInt32(rdr["ColumnName"]);
}

23
while(rdr.Read())
{
   string col=rdr["colName"].ToString();
}

to będzie działać


3
toString()nie jest ważne, powinno być .ToString()po prostu
fyi

1
@MethodMan dzięki za informacje. Zredagowałem moją odpowiedź zgodnie z twoją sugestią.
Mohini Mhetre

Cześć, jak ustawić wiersz jako obiekty, a nie według kolumn? Na przykład {id: 1, name: 'John'}
Binsoi

co jeśli chcę coś takiego poniżej. if (rdr [0]) {// zrób coś tutaj} else if (rdr [1]) {// zrób coś tutaj} Próbowałem rzucić to bool, ale daje to niepoprawny błąd rzutowania
Fahad Ejaz Butt

16

Pojedynczy wynik:

if (reader.Read())
{
    Response.Write(reader[0].ToString());
    Response.Write(reader[1].ToString());
}

W przypadku wielu wyników:

while (reader.Read())
{
    Response.Write(reader[0].ToString());
    Response.Write(reader[1].ToString());
}

15

Pomyślałem o udostępnieniu mojej metody pomocniczej tym, którzy mogą z niej korzystać:

public static class Sql
{
    public static T Read<T>(DbDataReader DataReader, string FieldName)
    {
        int FieldIndex;
        try { FieldIndex = DataReader.GetOrdinal(FieldName); }
        catch { return default(T); }

        if (DataReader.IsDBNull(FieldIndex))
        {
            return default(T);
        }
        else
        {
            object readData = DataReader.GetValue(FieldIndex);
            if (readData is T)
            {
                return (T)readData;
            }
            else
            {
                try
                {
                    return (T)Convert.ChangeType(readData, typeof(T));
                }
                catch (InvalidCastException)
                {
                    return default(T);
                }
            }
        }
    }
}

Stosowanie:

cmd.CommandText = @"SELECT DISTINCT [SoftwareCode00], [MachineID] 
                    FROM [CM_S01].[dbo].[INSTALLED_SOFTWARE_DATA]";
using (SqlDataReader data = cmd.ExecuteReader())
{
    while (data.Read())
    {
        usedBy.Add(
            Sql.Read<String>(data, "SoftwareCode00"), 
            Sql.Read<Int32>(data, "MachineID"));
    }
}

Metoda pomocnika rzutuje na dowolną wartość, którą chcesz, jeśli nie może rzutować lub wartość bazy danych jest równa NULL, wynik będzie równy null.


2
Niezły fragment kodu, zmodyfikowałem go tak, aby był metodą rozszerzającą i działa bardzo dobrzereader.GetColumn<int>("M_ID");
Ali Umair

8

Właściwie to sam doszedłem do wniosku, że mogę to zrobić:

while (rdr.read())
{  
  string str = rdr.GetValue().ToString().Trim();  
}

1
Nie widzę, jak to podejście jest bardziej skomplikowane niż inne. Trim()nie został wymieniony w pytaniu i tak jest tutaj, ale nie w innych odpowiedziach.
jwg

7

Wiem, że to trochę stare, ale jeśli czytasz zawartość SqlDataReader do klasy, będzie to bardzo przydatne. nazwy kolumn czytelnika i klasy powinny być takie same

public static List<T> Fill<T>(this SqlDataReader reader) where T : new()
        {
            List<T> res = new List<T>();
            while (reader.Read())
            {
                T t = new T();
                for (int inc = 0; inc < reader.FieldCount; inc++)
                {
                    Type type = t.GetType();
                    string name = reader.GetName(inc);
                    PropertyInfo prop = type.GetProperty(name);
                    if (prop != null)
                    {
                        if (name == prop.Name)
                        {
                            var value = reader.GetValue(inc);
                            if (value != DBNull.Value)
                            { 
                                prop.SetValue(t, Convert.ChangeType(value, prop.PropertyType), null);
                            }
                            //prop.SetValue(t, value, null);

                        }
                    }
                }
                res.Add(t);
            }
            reader.Close();

            return res;
        }

To powinna być zalecana odpowiedź. Bardzo ogólny sposób zwracania wpisanej listy.
kotpal

7

Uważam, przed użyciem SqlDataReadertutaj; ADO.NET ma wiele przypadków skrajnych i komplikacji, a z mojego doświadczenia wynika, że ​​większość ręcznie napisanego kodu ADO.NET jest zepsuta przynajmniej w jeden sposób (zwykle subtelny i kontekstowy).

Istnieją narzędzia, aby tego uniknąć. Na przykład w przypadku, gdy chcesz przeczytać kolumnę ciągów. Dapper sprawia, że ​​jest to całkowicie bezbolesne:

var region = ... // some filter
var vals = connection.Query<string>(
    "select Name from Table where Region=@region", // query
    new { region } // parameters
).AsList();

Dapper zajmuje się tutaj całą parametryzacją, wykonywaniem i przetwarzaniem wierszy - oraz wieloma innymi nieregularnymi szczegółami ADO.NET. <string>Można zastąpić <SomeType>materializować całe wiersze do obiektów.


6

Mówiąc najprościej, jeśli zapytanie zwraca nazwę_kolumny i zawiera ciąg:

while (rdr.Read())
{
    string yourString = rdr.getString("column_name")
}

1
Obecnie metody .getXXX czytnika akceptują tylko liczby całkowite porządkowe.
Cos Callis

3

Mam funkcję pomocniczą, taką jak:

  public static string GetString(object o)
    {
        if (o == DBNull.Value)
            return "";

        return o.ToString();
    }

następnie używam go do wyodrębnienia ciągu:

 tbUserName.Text = GetString(reader["UserName"]);

1
Standardowa Convert.ToString (o) robi to samo, ponieważ DBNull jest IConvertible, a DBNull.ToString () zwraca string.Empty.
nzeemin

Masz rację, ale nie jestem pewien, czy to zrobił, kiedy to opublikowałem.
JBrooks,

3

Zwykle czytam dane przez czytnik danych w ten sposób. właśnie dodałem mały przykład.

string connectionString = "Data Source=DESKTOP-2EV7CF4;Initial Catalog=TestDB;User ID=sa;Password=tintin11#";
string queryString = "Select * from EMP";

using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(queryString, connection))
            {
                connection.Open();

                using (SqlDataReader reader = command.ExecuteReader())
                {
                    if (reader.HasRows)
                    {
                        while (reader.Read())
                        {
                            Console.WriteLine(String.Format("{0}, {1}", reader[0], reader[1]));
                        }
                    }
                    reader.Close();
                }
            }

1

Musisz read database columntutaj. Możesz rzucić okiem na następujący fragment kodu

                string connectionString = ConfigurationManager.ConnectionStrings["NameOfYourSqlConnectionString"].ConnectionString;
                using (var _connection = new SqlConnection(connectionString))
                {
                    _connection.Open();

                    using (SqlCommand command = new SqlCommand("SELECT SomeColumnName FROM TableName", _connection))
                    {

                        SqlDataReader sqlDataReader = command.ExecuteReader();
                        if (sqlDataReader.HasRows)
                        {
                            while (sqlDataReader.Read())
                            {
                                string YourFirstDataBaseTableColumn = sqlDataReader["SomeColumn"].ToString(); // Remember Type Casting is required here it has to be according to database column data type
                                string YourSecondDataBaseTableColumn = sqlDataReader["SomeColumn"].ToString();
                                string YourThridDataBaseTableColumn = sqlDataReader["SomeColumn"].ToString();

                            }
                        }
                        sqlDataReader.Close();
                    }
                    _connection.Close();
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.