Ранее для получения данных мы использовали объект SqlDataReader, с помощью которого построчно можно перебрать ответ от сервера базы данных. Но есть и другой способ, который демонстрирует использование объектов DataSet.
Класс DataSet из пространства имен System.Data
представляет хранилище или кэш данных в памяти, извлеченных из источника данных.
Объект DataSet
содержит таблицы, которые представлены типом DataTable.
Таблица DataTable
, в свою очередь, состоит из столбцов и строк. Каждый столбец представляет объект
DataColumn, а строка - объект DataRow.
Для наполнения объекта DataSet данными из источника данных применяется класс System.Data.Common.DataAdapter
(который реализует
интерфейс System.Data.IDataAdapter
), а точнее его реализации, предназначенные для работы с определенной СУБД.
Для заполнения объекта DataSet у объекта DataAdapter
вызывается метод Fill(),
в который в качестве параметра передается заполняемый объект DataSet.
Метод Fill()
неявно открывает объект подключения, который хранится в свойстве Connection
объекта DataAdapter
, если это подключение не открыто. Если метод Fill()
открывает подключение,
то после получения данных метод Fill закрывает это подключение.
Если подключение до вызова метода Fill()
ранее уже было открыто, например, с помощью метода Open()/OpenAsync()
,
метод Fill просто использует это подключение.
Для работы с БД SQL Server пакет Microsoft.Data.SqlClient
как раз предоставляет реализацию DataAdapter в виде класса SqlDataAdapter.
Для получения данных через объект SqlDataAdapter необходимо организовать подключение к БД и выполнить команду SELECT. Есть несколько способов создания SqlDataAdapter:
SqlDataAdapter adapter = new SqlDataAdapter(); SqlDataAdapter adapter = new SqlDataAdapter(command); SqlDataAdapter adapter = new SqlDataAdapter(sql, connection); SqlDataAdapter adapter = new SqlDataAdapter(sql, connectionString);
Для работы SqlDataAdapter необходим объект SqlConnection, либо строка подключения и выполняемое SQL-выражение "SELECT".
Пример наполнения DataSet с помощью SqlDataAdapter:
using System; using System.Data; using Microsoft.Data.SqlClient; namespace HelloApp { class Program { static void Main(string[] args) { string connectionString = "Server=(localdb)\\mssqllocaldb;Database=adonetdb;Trusted_Connection=True;"; string sql = "SELECT * FROM Users"; using (SqlConnection connection = new SqlConnection(connectionString)) { // Создаем объект DataAdapter SqlDataAdapter adapter = new SqlDataAdapter(sql, connection); // Создаем объект DataSet DataSet ds = new DataSet(); // Заполняем Dataset adapter.Fill(ds); } Console.Read(); } } }
В этом случае в DataSet окажутся данные, извлеченные с помощью выражения SELECT * FROM Users
.
Объект DataSet состоит из набора объектов DataTable. Для доступа к таблицам в DataSet определено свойство Tables, которое представляет объект DataTableCollection.
Объект DataTable
, в свою очередь, состоит из набора объектов DataColumn - описания столбцов таблицы,
которые определяют схему таблицы и которые можно получить через свойство Columns.
Кроме столбцов класс DataTable
определяет свойство Rows, которое представляет тип DataRowCollection
и которое хранит строки таблицы. Каждая строка представляет класс DataRow.
Для обращения к отдельным ячейкам строки DataRow предлагает ряд свойств, из которых следует выделить следующие:
Item[Int32]: возвращает или устанавливает значение ячейки по ее индексу. Возвращает значение типа object.
Item[String]: возвращает или устанавливает значение ячейки по имени столбца. Возвращает значение типа object.
ItemArray: возвращает или устанавливает значения всех ячеек строки в виде объекта object[]
Теперь используем все выше рассмотренные типы, чтобы получить данные таблицы и вывести их содержимое на консоль:
using System; using System.Data; using Microsoft.Data.SqlClient; namespace HelloApp { class Program { static void Main(string[] args) { string connectionString = "Server=(localdb)\\mssqllocaldb;Database=adonetdb;Trusted_Connection=True;"; string sql = "SELECT * FROM Users"; using (SqlConnection connection = new SqlConnection(connectionString)) { // Создаем объект DataAdapter SqlDataAdapter adapter = new SqlDataAdapter(sql, connection); // Создаем объект Dataset DataSet ds = new DataSet(); // Заполняем Dataset adapter.Fill(ds); // Отображаем данные // перебор всех таблиц foreach (DataTable dt in ds.Tables) { foreach (DataColumn column in dt.Columns) Console.Write($"{column.ColumnName}\t"); Console.WriteLine(); // перебор всех строк таблицы foreach (DataRow row in dt.Rows) { // получаем все ячейки строки var cells = row.ItemArray; foreach (object cell in cells) Console.Write($"{cell}\t"); Console.WriteLine(); } } } Console.Read(); } } }
Консольный вывод в моем случае:
Id Age Name 2 32 Alice 3 28 Bob 19 36 Tom 22 34 Tim 23 31 Kate
Хотя DataSet представляет самодостаточный класс, с которым можно работать вне зависимости от применяемой технологии на .NET, однако чаще всего он применяется именно для связи элементов управления для отображения данных c БД, например, элемента DataGridView в Windows Forms.