Ler dados do SqlDataReader

157

Eu tenho um banco de dados do SQL Server 2008 e estou trabalhando nele no back-end. Estou trabalhando em asp.net/C#

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

Eu sei que o leitor tem valores. Meu comando SQL é selecionar apenas 1 coluna de uma tabela. A coluna contém apenas seqüências de caracteres. Eu quero ler as strings (linhas) no leitor, uma por uma. Como eu faço isso?

zack
fonte

Respostas:

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

ou

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

Estes são objects, então você precisa convertê-los ou .ToString().

Mark Avenius
fonte
3
Se o operador [] retornar um objeto, será necessário convertê-lo como uma string.
Scott Chamberlain
Se você usar índices como o reader.GetString (0), ele usará a primeira coluna que você selecionou na sua consulta ou a primeira coluna na tabela. Eu tenho uma tabela com 3 colunas em ordem: ID, Dir, Email. Meu comando seleciona dir e email. O reader.GetStrting (0) recuperará dir ou ID? Os índices são baseados na própria tabela no SQL Server ou na consulta que você executou para selecionar colunas de uma tabela?
Shenk
1
@shenk Os índices são baseados na ordem dos parâmetros selecionados. De qualquer maneira, você é melhor fora de usar os nomes de coluna ou aliases (ou seja rdr [ "ID"] em oposição a rdr [0])
Mark Avenius
1
@MarkAvenius que costumava ser que a indexação via ordinais numéricas ganhou uma melhoria de desempenho sobre os nomes das colunas / aliases - não tenho certeza se isso ainda é o caso
BaltoStar
3
@BaltoStar que é interessante; Eu não estava ciente disso. No entanto, dependendo da diferença de desempenho (especialmente em comparação com a transmissão de dados por fio, com base no seu aplicativo), eu geralmente diria que a legibilidade e a manutenção da visualização dos nomes das colunas superariam qualquer melhoria marginal no desempenho. Obrigado!
Mark Avenius
36

Coloque o nome da coluna e comece a retornar do banco de dados onde "ColumnName"está. Se for uma string, você pode usar .ToString(). Se for outro tipo, você precisará convertê-lo usando System.Convert.

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

vai funcionar

Mohini Mhetre
fonte
3
toString()não é válido deve ser .ToString()apenas fyi
MethodMan
1
@MethodMan, obrigado pela sua informação. Eu editei minha resposta conforme sua sugestão.
Mohini Mhetre
Oi, como faço para obter a linha como objetos e não por coluna? Por exemplo {id: 1, nome: 'John'}
Binsoi 22/11
e se eu quiser algo como abaixo. if (RDR [0]) {// fazer alguma coisa aqui} else if (RDR [1]) {// fazer alguma coisa aqui} eu tinha tentar lançá-lo bool mas seu dá erro elenco invaild
Fahad Ejaz Bundas
16

Para um único resultado:

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

Para vários resultados:

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

Pensei em compartilhar meu método auxiliar para aqueles que podem usá-lo:

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

O método auxiliar converte para qualquer valor que você desejar, se não puder converter ou o valor do banco de dados for NULL, o resultado será nulo.

Tiele Declercq
fonte
2
Bom pedaço de código, i modificado para ser um método de extensão e funciona muito bemreader.GetColumn<int>("M_ID");
Ali Umair
8

Na verdade, eu mesmo descobri que poderia fazer isso:

while (rdr.read())
{  
  string str = rdr.GetValue().ToString().Trim();  
}
zack
fonte
1
Não vejo como essa abordagem é mais complicada do que as outras. Trim()não foi mencionado na pergunta e, portanto, está aqui, mas não nas outras respostas.
Jwg
7

Eu sei que isso é meio antigo, mas se você estiver lendo o conteúdo de um SqlDataReader em uma classe, isso será muito útil. os nomes das colunas do leitor e da classe devem ser os mesmos

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
fonte
Esta deve ser a resposta recomendada. Maneira muito genérica de retornar uma lista digitada.
kotpal 13/06
7

Eu argumentaria contra usar SqlDataReaderaqui; O ADO.NET tem muitos casos extremos e complicações e, na minha experiência, o código ADO.NET mais escrito manualmente é quebrado de pelo menos uma maneira (geralmente sutil e contextual).

Existem ferramentas para evitar isso. Por exemplo, no caso aqui, você deseja ler uma coluna de strings. Dapper torna isso completamente indolor:

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

O Dapper aqui está lidando com toda a parametrização, execução e processamento de linha - e muitos outros detalhes obscuros do ADO.NET. O <string>pode ser substituído por <SomeType>materializar linhas inteiras em objetos.

Marc Gravell
fonte
6

Nos termos mais simples, se sua consulta retornar column_name e ela contiver uma string:

while (rdr.Read())
{
    string yourString = rdr.getString("column_name")
}
Dekker500
fonte
1
Atualmente, os métodos .getXXX no leitor aceitam apenas um ordinal inteiro.
quer
3

Eu tenho uma função auxiliar como:

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

        return o.ToString();
    }

então eu uso para extrair a string:

 tbUserName.Text = GetString(reader["UserName"]);
JBrooks
fonte
1
O padrão Convert.ToString (o) faz o mesmo, porque DBNull é IConvertible e DBNull.ToString () retorna string.Empty.
Nzeemin 17/09/2015
Você está correto, mas não tenho certeza de que fez isso quando publiquei isso.
JBrooks
3

Normalmente leio dados pelo leitor de dados dessa maneira. acabou de adicionar um pequeno exemplo.

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();
                }
            }
Névoa
fonte
1

Você tem que read database columnaqui. Você pode dar uma olhada no seguinte snippet 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
fonte