Lesen Sie Daten aus SqlDataReader

157

Ich habe eine SQL Server 2008-Datenbank und arbeite im Backend daran. Ich arbeite an asp.net/C#

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

Ich weiß, dass der Leser Werte hat. Mein SQL-Befehl besteht darin, nur eine Spalte aus einer Tabelle auszuwählen. Die Spalte enthält NUR Zeichenfolgen. Ich möchte die Zeichenfolgen (Zeilen) im Reader einzeln lesen. Wie mache ich das?

Zack
quelle

Antworten:

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);
    }
}
Scott Chamberlain
quelle
106
string col1Value = rdr["ColumnOneName"].ToString();

oder

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

Dies sind objects, also musst du sie entweder besetzen oder .ToString().

Mark Avenius
quelle
3
Der Operator [] gibt ein Objekt zurück. Sie müssen es als Zeichenfolge umwandeln.
Scott Chamberlain
Wenn Sie Indizes wie reader.GetString (0) verwenden, wird die erste Spalte verwendet, die Sie in Ihrer Abfrage ausgewählt haben, oder die erste Spalte in der Tabelle. Ich habe eine Tabelle mit 3 Spalten in der Reihenfolge: ID, Dir, Email. Mein Befehl wählt dir und email aus. Wird reader.GetStrting (0) Verzeichnis oder ID abrufen? Basieren die Indizes auf der Tabelle selbst in SQL Server oder auf der Abfrage, die Sie ausgeführt haben, um Spalten aus einer Tabelle auszuwählen?
Shenk
1
@shenk Die Indizes basieren auf der Reihenfolge Ihrer ausgewählten Parameter. In beiden Fällen ist es besser, die Spaltennamen oder Aliase (dh rdr ["ID"] im Gegensatz zu rdr [0]) zu verwenden
Mark Avenius
1
@ MarkAvenius Früher war es so, dass die Indizierung über numerische Ordnungszahlen eine Leistungsverbesserung gegenüber Spaltennamen / Aliasen erzielte - nicht sicher, ob dies immer noch der Fall ist
BaltoStar
3
@BaltoStar das ist interessant; Das war mir nicht bewusst. Abhängig vom Leistungsunterschied (insbesondere im Vergleich zum Übertragen von Daten über das Netzwerk, basierend auf Ihrer Anwendung) würde ich jedoch allgemein sagen, dass die Lesbarkeit und Wartbarkeit der Spaltennamen jede geringfügige Verbesserung der Leistung übertrumpfen würde. Vielen Dank!
Mark Avenius
36

Geben Sie den Namen des Spaltenbeginns ein, der von der Datenbank zurückgegeben wird, in der er sich "ColumnName"befindet. Wenn es sich um eine Zeichenfolge handelt, können Sie diese verwenden .ToString(). Wenn es sich um einen anderen Typ handelt, müssen Sie ihn mit konvertieren System.Convert.

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

es wird funktionieren

Mohini Mhetre
quelle
3
toString()ist nicht gültig sollte .ToString()nur fyi sein
MethodMan
1
@ MethodMan danke für deine Informationen. Ich habe meine Antwort gemäß Ihrem Vorschlag bearbeitet.
Mohini Mhetre
HI, wie bekomme ich die Zeile als Objekte und nicht nach Spalten? Zum Beispiel {id: 1, name: 'John'}
Binsoi
Was ist, wenn ich so etwas wie unten will? if (rdr [0]) {// hier etwas tun} else if (rdr [1]) {// hier etwas tun} Ich hatte versucht, es bool zu wirken, aber es gibt einen Invaild-Cast-Fehler
Fahad Ejaz Butt
16

Für ein einzelnes Ergebnis:

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

Für mehrere Ergebnisse:

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

Ich dachte, ich möchte meine Hilfsmethode für diejenigen teilen, die sie verwenden können:

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);
                }
            }
        }
    }
}

Verwendung:

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"));
    }
}

Die Hilfsmethode wird in einen beliebigen Wert umgewandelt. Wenn sie nicht umgewandelt werden kann oder der Datenbankwert NULL ist, ist das Ergebnis null.

Tiele Declercq
quelle
2
Schönes Stück Code, ich habe es geändert, um eine Erweiterungsmethode zu sein und funktioniert sehr gutreader.GetColumn<int>("M_ID");
Ali Umair
8

Eigentlich habe ich selbst herausgefunden, dass ich das tun kann:

while (rdr.read())
{  
  string str = rdr.GetValue().ToString().Trim();  
}
Zack
quelle
1
Ich sehe nicht, wie dieser Ansatz komplizierter ist als die anderen. Trim()wurde in der Frage nicht erwähnt und ist hier aber nicht in den anderen Antworten.
JWG
7

Ich weiß, dass dies etwas alt ist, aber wenn Sie den Inhalt eines SqlDataReader in eine Klasse einlesen, ist dies sehr praktisch. Die Spaltennamen von Leser und Klasse sollten identisch sein

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;
        }
Ali Umair
quelle
Dies sollte Antwort empfohlen werden. Sehr allgemeiner Weg, um eine typisierte Liste zurückzugeben.
Kotpal
7

Ich würde behaupten , gegen Verwendung von SqlDataReaderhier; ADO.NET hat viele Randfälle und Komplikationen, und meiner Erfahrung nach ist der meiste manuell geschriebene ADO.NET-Code auf mindestens eine Weise fehlerhaft (normalerweise subtil und kontextbezogen).

Es gibt Tools, um dies zu vermeiden. In diesem Fall möchten Sie beispielsweise eine Spalte mit Zeichenfolgen lesen. Dapper macht das völlig schmerzlos:

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

Dapper befasst sich hier mit der gesamten Parametrisierung, Ausführung und Zeilenverarbeitung - und vielen anderen Details von ADO.NET. Das <string>kann durch ersetzt werden, <SomeType>um ganze Zeilen zu Objekten zu materialisieren.

Marc Gravell
quelle
6

Im einfachsten Fall, wenn Ihre Abfrage Spaltenname zurückgibt und eine Zeichenfolge enthält:

while (rdr.Read())
{
    string yourString = rdr.getString("column_name")
}
Dekker500
quelle
1
Gegenwärtig akzeptieren die .getXXX-Methoden auf dem Reader nur eine ganzzahlige Ordnungszahl.
Cos Callis
3

Ich habe eine Hilfsfunktion wie:

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

        return o.ToString();
    }

dann benutze ich es, um den String zu extrahieren:

 tbUserName.Text = GetString(reader["UserName"]);
JBrooks
quelle
1
Standard Convert.ToString (o) macht dasselbe, da DBNull IConvertible ist und DBNull.ToString () string.Empty zurückgibt.
Nzeemin
Sie haben Recht, aber ich bin mir nicht sicher, ob dies der Fall war, als ich dies gepostet habe.
JBrooks
3

Normalerweise lese ich Daten mit dem Datenleser auf diese Weise. habe gerade ein kleines Beispiel hinzugefügt.

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();
                }
            }
Nebel
quelle
1

Du musst read database columnhier sein. Sie können sich das folgende Code-Snippet ansehen

                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();
Md Farid Uddin Kiron
quelle