Чтение данных из SqlDataReader

157

У меня есть база данных SQL Server 2008, и я работаю над этим в бэкэнде. Я работаю на asp.net/C#

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

Я знаю, что у читателя есть ценности. Моя команда SQL состоит в том, чтобы выбрать только 1 столбец из таблицы. Столбец содержит ТОЛЬКО строки. Я хочу прочитать строки (строки) в читателе по одной. Как мне это сделать?

Zack
источник

Ответы:

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

или

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

Это objects, так что вам нужно либо разыграть их, либо .ToString().

Марк Авениус
источник
3
Оператор [] возвращает объект, вам нужно будет привести его как строку.
Скотт Чемберлен
Если вы используете индексы, такие как reader.GetString (0), он будет использовать первый столбец, выбранный вами в запросе, или первый столбец таблицы. У меня есть таблица с 3 столбцами по порядку: ID, Dir, Email. Моя команда выбирает каталог и адрес электронной почты. Будет ли reader.GetStrting (0) получать каталог или ID? Основаны ли индексы на самой таблице на SQL Server или на запросе, который вы выполняли для выбора столбцов из таблицы?
Шенк
1
@shenk Индексы основаны на порядке ваших выбранных параметров. В любом случае вам лучше использовать имена столбцов или псевдонимы (т. Е. Rdr ["ID"], а не rdr [0])
Марк Авениус
1
@MarkAvenius Раньше было так, что индексирование с помощью числовых порядковых номеров улучшало производительность по сравнению с именами / псевдонимами столбцов - не уверен, что это все еще так
BaltoStar
3
@BaltoStar это интересно; Я не знал об этом. Однако, в зависимости от разницы в производительности (особенно по сравнению с передачей данных по проводам в зависимости от вашего приложения), я бы сказал, что удобочитаемость и удобство просмотра имен столбцов будут превосходить любое незначительное улучшение производительности. Спасибо!
Марк Авениус
36

Поставьте имя столбца начала, возвращенного из базы данных, где "ColumnName"находится. Если это строка, вы можете использовать .ToString(). Если это другой тип, вам нужно конвертировать его, используя 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();
}

это будет работать

Мохини Метре
источник
3
toString()недействительно должно быть .ToString()просто к вашему сведению
MethodMan
1
@MethodMan спасибо за вашу информацию. Я отредактировал свой ответ согласно вашему предложению.
Мохини Метре
Привет, Как я могу получить строку как объекты, а не по столбцу? Например, {id: 1, name: 'John'}
Binsoi
Что делать, если я хочу что-то вроде ниже. if (rdr [0]) {// сделать что-то здесь} в противном случае if (rdr [1]) {// сделать что-то здесь} Я попытался привести его к bool, но он выдает ошибку
вызова invaild
16

Для одного результата:

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

Для нескольких результатов:

while (reader.Read())
{
    Response.Write(reader[0].ToString());
    Response.Write(reader[1].ToString());
}
Писет Сок
источник
15

Мысль поделиться моим вспомогательным методом для тех, кто может его использовать:

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

Использование:

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

Вспомогательный метод приводит к любому значению, которое вам нравится, если оно не может быть приведено или значение базы данных равно NULL, результат будет нулевым.

Тиле Деклерк
источник
2
Хороший кусок кода, я изменил его, чтобы он был методом расширения и работает очень хорошоreader.GetColumn<int>("M_ID");
Али Умайр
8

На самом деле, я сам понял, что могу сделать это:

while (rdr.read())
{  
  string str = rdr.GetValue().ToString().Trim();  
}
Zack
источник
1
Я не вижу, как этот подход сложнее, чем другие. Trim()не был упомянут в вопросе и так же здесь, но не в других ответах.
JWG
7

Я знаю, что это немного по-старому, но если вы читаете содержимое SqlDataReader в класс, то это будет очень удобно. имена столбцов читателя и класса должны быть одинаковыми

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;
        }
Али Умайр
источник
На это следует рекомендовать ответ. Очень общий способ возврата типизированного списка.
Котпал
7

Я бы поспорил против использования SqlDataReaderздесь; ADO.NET имеет множество крайних случаев и сложностей, и, по моему опыту, написанный вручную код ADO.NET разбивается по крайней мере одним способом (обычно тонким и контекстным).

Инструменты существуют, чтобы избежать этого. Например, в случае здесь вы хотите прочитать столбец строк. Dapper делает это совершенно безболезненным:

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

Dapper здесь имеет дело со всей параметризацией, выполнением и обработкой строк - и множеством других шероховатых деталей ADO.NET. <string>Можно заменить <SomeType>материализовать целые строки в объекты.

Марк Гравелл
источник
6

Проще говоря, если ваш запрос возвращает column_name и содержит строку:

while (rdr.Read())
{
    string yourString = rdr.getString("column_name")
}
Dekker500
источник
1
В настоящее время методы .getXXX для читателя принимают только целочисленный порядковый номер.
Cos Callis
3

У меня есть вспомогательная функция, как:

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

        return o.ToString();
    }

затем я использую его для извлечения строки:

 tbUserName.Text = GetString(reader["UserName"]);
JBrooks
источник
1
Стандартный Convert.ToString (o) делает то же самое, потому что DBNull является IConvertible, а DBNull.ToString () возвращает string.Empty.
nzeemin
Вы правы, но я не уверен, что это произошло, когда я опубликовал это.
ДжБрукс
3

Я обычно читаю данные читателем данных таким образом. просто добавил небольшой пример.

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

Вы должны read database columnздесь. Вы могли бы посмотреть на следующий фрагмент кода

                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();
Фарид Уддин Кирон
источник