Leer datos de SqlDataReader

157

Tengo una base de datos SQL Server 2008 y estoy trabajando en ella en el backend. Estoy trabajando en asp.net/C#

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

Sé que el lector tiene valores. Mi comando SQL es seleccionar solo 1 columna de una tabla. La columna contiene cadenas SOLAMENTE. Quiero leer las cadenas (filas) en el lector una por una. ¿Cómo hago esto?

zack
fuente

Respuestas:

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

o

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

Estos son objects, por lo que debes lanzarlos o .ToString().

Mark Avenius
fuente
3
el operador [] devuelve un objeto, deberá convertirlo como una cadena.
Scott Chamberlain
Si usa índices como reader.GetString (0) usará la primera columna que seleccionó en su consulta o la primera columna de la tabla. Tengo una tabla con 3 columnas en orden: ID, Dir, Correo electrónico. Mi comando selecciona dir y correo electrónico. ¿Lector.GetStrting (0) recuperará dir o ID? ¿Los índices se basan en la tabla misma en SQL Server o en la consulta que ejecutó para seleccionar columnas de una tabla?
shenk
1
@shenk Los índices se basan en el orden de los parámetros seleccionados. De cualquier manera, es mejor usar los nombres de columna o alias (es decir, rdr ["ID"] en lugar de rdr [0])
Mark Avenius
1
@ Mark Avenius solía ser que la indexación a través de ordinales numéricos obtuvo una mejora en el rendimiento sobre los nombres / alias de columnas, no estoy seguro de si ese es el caso
BaltoStar el
3
@BaltoStar que es interesante; No estaba al tanto de eso. Sin embargo, dependiendo de la diferencia en el rendimiento (especialmente en comparación con el envío de datos por cable, según su aplicación), generalmente diría que la legibilidad y la facilidad de mantenimiento de ver los nombres de las columnas superarían cualquier mejora marginal en el rendimiento. ¡Gracias!
Mark Avenius
36

Poner el nombre de la columna comenzar devuelto desde la base de datos donde "ColumnName"está. Si es una cadena, puede usar .ToString(). Si es otro tipo, debe convertirlo usando System.Convert.

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

funcionará

Mohini Mhetre
fuente
3
toString()no es válido debería ser .ToString()solo para tu información
MethodMan
1
@MethodMan gracias por tu información. Edité mi respuesta según su sugerencia.
Mohini Mhetre
Hola, ¿cómo obtengo la fila como objetos y no por columna? Por ejemplo {id: 1, nombre: 'John'}
Binsoi
¿Qué pasa si quiero algo como a continuación? if (rdr [0]) {// haz algo aquí} más if (rdr [1]) {// haz algo aquí} Intenté lanzarlo bool pero me da un error de lanzamiento invadido
Fahad Ejaz Butt
16

Para un solo resultado:

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

Para múltiples resultados:

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

Pensé en compartir mi método de ayuda para aquellos que pueden usarlo:

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

Uso:

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

El método auxiliar convierte a cualquier valor que desee, si no puede emitir o el valor de la base de datos es NULL, el resultado será nulo.

Tiele Declercq
fuente
2
Buen código, lo modifiqué para que sea un método de extensión y funciona muy bienreader.GetColumn<int>("M_ID");
Ali Umair
8

En realidad, me di cuenta de que podía hacer esto:

while (rdr.read())
{  
  string str = rdr.GetValue().ToString().Trim();  
}
zack
fuente
1
No veo cómo este enfoque es más complicado que los demás. Trim()no se mencionó en la pregunta y también lo está aquí, pero no en las otras respuestas.
jwg
7

Sé que esto es un poco antiguo, pero si está leyendo el contenido de un SqlDataReader en una clase, esto será muy útil. los nombres de columna del lector y la clase deben ser iguales

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
fuente
Esta debería ser la respuesta recomendada. Manera muy genérica de devolver una lista escrita.
Kotpal
7

Yo argumentaría en contra de usar SqlDataReaderaquí; ADO.NET tiene muchos casos extremos y complicaciones, y en mi experiencia, la mayoría del código ADO.NET escrito manualmente se rompe al menos de una manera (generalmente sutil y contextual).

Existen herramientas para evitar esto. Por ejemplo, en el caso aquí, desea leer una columna de cadenas. Dapper lo hace completamente indoloro:

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

Dapper aquí se ocupa de toda la parametrización, ejecución y procesamiento de filas, y muchos otros detalles sucios de ADO.NET. Se <string>puede reemplazar con <SomeType>para materializar filas enteras en objetos.

Marc Gravell
fuente
6

En los términos más simples, si su consulta devuelve column_name y contiene una cadena:

while (rdr.Read())
{
    string yourString = rdr.getString("column_name")
}
Dekker500
fuente
1
En la actualidad, los métodos .getXXX en el lector solo aceptan un ordinal entero.
Cos Callis
3

Tengo una función auxiliar como:

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

        return o.ToString();
    }

luego lo uso para extraer la cadena:

 tbUserName.Text = GetString(reader["UserName"]);
JBrooks
fuente
1
Convert.ToString estándar (o) hace lo mismo, porque DBNull es IConvertible y DBNull.ToString () devuelve string.Empty.
nzeemin
Estás en lo correcto, pero no estoy seguro de que lo haya hecho cuando publiqué esto.
JBrooks
3

Usualmente leo datos por lector de datos de esta manera. Acabo de agregar un pequeño ejemplo.

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();
                }
            }
Niebla
fuente
1

Tienes que read database column aqui Puedes echar un vistazo al siguiente fragmento de código

                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
fuente