Данное руководство устарело. Актуальное руководство: по ADO.NET и работе с базами данных в .NET 6
В прошлой теме мы рассмотрели, как выполнять команды с помощью метода 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(); }
Консольный вывод:
Для выборки данных из БД используется 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(); } }