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


157

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

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

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

Ответы:


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

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

1
В настоящее время методы .getXXX для читателя принимают только целочисленный порядковый номер.
Cos Callis

3

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

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

        return o.ToString();
    }

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

 tbUserName.Text = GetString(reader["UserName"]);

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();
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.