Чтение результатов запроса и SqlDataReader

Данное руководство устарело. Актуальное руководство: по ADO.NET и работе с базами данных в .NET 6

Последнее обновление: 31.10.2015

В прошлой теме мы рассмотрели, как выполнять команды с помощью метода ExecuteNonOuery(), однако если мы хотим считывать данные, которые хранятся в таблице, то нам потребуется другой метод - ExecuteReader(). Этот метод возвращает объект SqlDataReader, который используется для чтения данных. Так, получим все данные из таблицы Users и выведем их на консоль:

static void Main(string[] args)
{
    string connectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=usersdb;Integrated Security=True";

    string sqlExpression = "SELECT * FROM Users";
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();
        SqlCommand command = new SqlCommand(sqlExpression, connection);
        SqlDataReader reader = command.ExecuteReader();

        if(reader.HasRows) // если есть данные
        {
            // выводим названия столбцов
            Console.WriteLine("{0}\t{1}\t{2}", reader.GetName(0), reader.GetName(1), reader.GetName(2));

            while (reader.Read()) // построчно считываем данные
            {
                object id = reader.GetValue(0);
                object name = reader.GetValue(1);
                object age = reader.GetValue(2);

                Console.WriteLine("{0} \t{1} \t{2}", id, name, age);
            }
        }
        
        reader.Close();
    }
            
    Console.Read();
}

Консольный вывод:

SqlDataReader в ADO.NET

Для выборки данных из БД используется sql-выражение SELECT. В данном случае мы выбираем все столбцы всех строк таблицы. Получив при выполнении запроса объект SqlDataReader, мы можем считать все полученные данные.

Но вначале мы проверяем, а есть ли вообще данные с помощью свойства HasRows. Если данные есть, то выводим заголовки таблицы с помощью методов reader.GetName(). Причем мы получаем столбцы в выборке именно в том порядке, в котором они определены в таблицы. То есть если вторым в таблицы идет столбец "Name", то чтобы получить его столбец применяется метод GetName(1) (так как нумерация столбцов идет с нуля).

Далее считываем сами данные. С помощью метода reader.Read() ридер переходит к следующей строке и возвращает булевое значение, которое указывает, есть ли данные для считывания.

В цикле while (reader.Read()) в порядке следования столбов получаем данные с помощью метода GetValue(), который возвращает данные в виде объекта типа object. Например, столбец Id идет первым и представляет целое число, поэтому для его получения применяется метод reader.GetValue(0). А столбец Name идет вторым, поэтому его значения получаем с помощью reader.GetValue(1).

После завершения работы с SqlDataReader надо его закрыть методом Close(). И пока один SqlDataReader не закрыт, другой объект SqlDataReader для одного и того же подключения мы использовать не сможем.

В качестве альтернативы мы могли бы обращаться к данным через название параметра:

while (reader.Read())
{
    object id = reader["id"];
    object name = reader["name"];
    object age = reader["age"];
    Console.WriteLine("{0} \t{1} \t{2}", id, name, age);
}

В этом случае результат будет аналогичным.

Асинхронное чтение

Для асинхронного чтения, во-первых, применяется метод ExecuteReaderAsync() класса SqlCommand, и во-вторых, метод ReadAsync() класса SqlDataReader:

static void Main(string[] args)
{
    ReadDataAsync().GetAwaiter();

    Console.Read();
}

private static async Task ReadDataAsync()
{
    string connectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=usersdb;Integrated Security=True";

    string sqlExpression = "SELECT * FROM Users";
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        await connection.OpenAsync();
        SqlCommand command = new SqlCommand(sqlExpression, connection);
        SqlDataReader reader = await command.ExecuteReaderAsync();

        if (reader.HasRows)
        {
            // выводим названия столбцов
            Console.WriteLine("{0}\t{1}\t{2}", reader.GetName(0), reader.GetName(1), reader.GetName(2));

            while (await reader.ReadAsync())
            {
                object id = reader.GetValue(0);
                object name = reader.GetValue(1);
                object age = reader.GetValue(2);
                Console.WriteLine("{0} \t{1} \t{2}", id, name, age);
            }
        }
        reader.Close();
    }
}
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850