Чтение результатов запроса и SqlDataReader
В прошлой теме мы рассмотрели, как выполнять команды с помощью метода 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();
}
}
Достарыңызбен бөлісу: |