Lire les données de SqlDataReader

157

J'ai une base de données SQL Server 2008 et j'y travaille dans le backend. Je travaille sur asp.net/C#

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

Je sais que le lecteur a des valeurs. Ma commande SQL consiste à sélectionner une seule colonne dans une table. La colonne contient des chaînes UNIQUEMENT. Je veux lire les chaînes (lignes) dans le lecteur une par une. Comment puis-je faire cela?

zack
la source

Réponses:

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
la source
106
string col1Value = rdr["ColumnOneName"].ToString();

ou

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

Ce sont des objects, vous devez donc les lancer ou les lancer .ToString().

Mark Avenius
la source
3
l'opérateur [] renvoie un objet, vous devrez le convertir en chaîne.
Scott Chamberlain
Si vous utilisez des index comme reader.GetString (0), il utilisera la première colonne que vous avez sélectionnée dans votre requête ou la première colonne de la table. J'ai une table avec 3 colonnes dans l'ordre: ID, Dir, Email. Ma commande sélectionne dir et email. Reader.GetStrting (0) va-t-il récupérer le répertoire ou l'ID? Les index sont-ils basés sur la table elle-même sur SQL Server ou sur la requête que vous avez exécutée pour sélectionner des colonnes dans une table?
shenk
1
@shenk Les index sont basés sur l'ordre de vos paramètres de sélection. Dans tous les cas, il vaut mieux utiliser les noms de colonnes ou les alias (c'est-à-dire rdr ["ID"] par opposition à rdr [0])
Mark Avenius
1
@MarkAvenius, l'indexation via des ordinaux numériques améliorait les performances des noms de colonnes / alias
je
3
@BaltoStar c'est intéressant; Je n'étais pas au courant de cela. Cependant, en fonction de la différence de performances (en particulier par rapport à la transmission de données sur le fil, en fonction de votre application), je dirais généralement que la lisibilité et la maintenabilité de voir les noms de colonnes l'emporteraient sur toute amélioration marginale des performances. Merci!
Mark Avenius
36

Mettez le nom du début de la colonne renvoyé par la base de données où se "ColumnName"trouve. S'il s'agit d'une chaîne, vous pouvez utiliser .ToString(). S'il s'agit d'un autre type, vous devez le convertir en utilisant System.Convert.

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

ça fonctionnera

Mohini Mhetre
la source
3
toString()n'est pas valide devrait être .ToString()juste fyi
MethodMan
1
@MethodMan merci pour vos informations. J'ai modifié ma réponse selon votre suggestion.
Mohini Mhetre
HI, Comment obtenir la ligne sous forme d'objets et non par colonne? Par exemple {id: 1, name: 'John'}
Binsoi
et si je veux quelque chose comme ci-dessous. if (rdr [0]) {// faites quelque chose ici} else if (rdr [1]) {// faites quelque chose ici} J'avais essayé de le cast bool mais cela donne une erreur de cast invaild
Fahad Ejaz Butt
16

Pour un seul résultat:

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

Pour des résultats multiples:

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

Pensé pour partager ma méthode d'aide pour ceux qui peuvent l'utiliser:

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

Usage:

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

La méthode d'assistance convertit en n'importe quelle valeur que vous aimez, si elle ne peut pas convertir ou si la valeur de la base de données est NULL, le résultat sera nul.

Tiele Declercq
la source
2
Beau morceau de code, je l'ai modifié pour être une méthode d'extension et fonctionne très bienreader.GetColumn<int>("M_ID");
Ali Umair
8

En fait, j'ai compris moi-même que je pouvais faire ceci:

while (rdr.read())
{  
  string str = rdr.GetValue().ToString().Trim();  
}
zack
la source
1
Je ne vois pas en quoi cette approche est plus compliquée que les autres. Trim()n'a pas été mentionné dans la question et il en est de même ici, mais pas dans les autres réponses.
jwg
7

Je sais que c'est un peu vieux, mais si vous lisez le contenu d'un SqlDataReader dans une classe, alors ce sera très pratique. les noms de colonne du lecteur et de la classe doivent être identiques

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
la source
Cela devrait être une réponse recommandée. Manière très générique de renvoyer une liste tapée.
kotpal
7

Je dirais contre l' utilisation SqlDataReaderici; ADO.NET a beaucoup de cas extrêmes et de complications, et d'après mon expérience, la plupart du code ADO.NET écrit manuellement est cassé d' au moins une manière (généralement subtile et contextuelle).

Des outils existent pour éviter cela. Par exemple, dans le cas où vous souhaitez lire une colonne de chaînes. Dapper rend cela totalement indolore:

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

Dapper traite ici de tout le paramétrage, de l'exécution et du traitement des lignes - et de nombreux autres détails grungy d'ADO.NET. Le <string>peut être remplacé par <SomeType>pour matérialiser des lignes entières en objets.

Marc Gravell
la source
6

En termes simples, si votre requête renvoie nom_colonne et contient une chaîne:

while (rdr.Read())
{
    string yourString = rdr.getString("column_name")
}
Dekker500
la source
1
Actuellement, les méthodes .getXXX sur le lecteur n'acceptent qu'un nombre entier.
Cos Callis
3

J'ai une fonction d'assistance comme:

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

        return o.ToString();
    }

puis je l'utilise pour extraire la chaîne:

 tbUserName.Text = GetString(reader["UserName"]);
JBrooks
la source
1
Standard Convert.ToString (o) fait de même, car DBNull est IConvertible et DBNull.ToString () renvoie string.Empty.
nzeemin
Vous avez raison, mais je ne suis pas sûr que ce soit le cas lorsque j'ai publié ceci.
JBrooks
3

Je lis généralement les données par lecteur de données de cette façon. vient d'ajouter un petit exemple.

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();
                }
            }
Brouillard
la source
1

Vous devez read database columnici. Vous pouvez jeter un œil à l'extrait de code suivant

                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
la source