В статье «ADO.Net. Элементы теории» отмечалось, что двумя основными компонентами ADO.NET для доступа к данным и их обработки являются поставщики данных .NET Framework и DataSet. На примере реляционной модели БД будет показано, как создать единую кодовую базу с помощью обобщенных типов доступа к данным (библиотека System.Data.Common) и конфигурационных файлов. В примере используется БД автотранспортного предприятия Garage из статьи «Создание базы данных SQL Server«.
В примере «Продажа билетов в кинотеатре» для источника подключения — «Файл базы данных Microsoft Access» доступен единственный поставщик данных — .Net Framework для OLE DB. Для работы с БД на основе SQL Server необходим поставщик данных SqlClient, для других источников данных потребуется Odbs. Возможно ли написать код программы, независимый от конкретного поставщика? Ведь в библиотеке System.Data.Common содержится описание классов, наследуемых в библиотеках System.Data.SqlClient, System.Data.OleDb и System.Data.Odbc.
Постановка задачи
Используя файл конфигурации App.config и сборку System.Configuration, а также классы библиотеки System.Data.Common написать приложение, в котором явно не указывается конкретный поставщик данных.
Решение
1) Создадим в Visual Studio 2017 Community консольное приложение ГенераторПоставщиковДанных. Добавим сразу оператор using System.Data.Common;
2) Добавим оператор using System.Configuration;
Примечание. Рекомендуется проверить наличие ссылки на эту сборку, для чего выберите Проект/Добавить ссылку, после чего в окне «Менеджер ссылок» отметить позицию System.Configuration и нажать Ok.
3) Откройте для редактирования файл App.config (Если его нет в вашем проекте, добавьте его: Проект/Добавление нового элемента/Файл конфигурации приложения). В редакторе кода App.config добавьте элемент <appSettings> с двумя ключами (key): «provider» со значением «System.Data.SqlClient» и «conStr» с указанием подключения к базе данных Garage (см. предыдущий пример). Подключение к БД получите через Обозреватель объектов SQL Server, кликнув правой кнопкой на БД Garage, и в окне Свойства объекта Garage скопируйте строку подключения, у меня, например:
Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Garage;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False
Текст файла App.config:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /> </startup> <appSettings> <!-- Поставщик --> <add key="provider" value="System.Data.SqlClient"/> <!-- Строка подключения --> <add key="conStr" value="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Garage; Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False; ApplicationIntent=ReadWrite;MultiSubnetFailover=False"/> </appSettings> </configuration>
Теперь все необходимое находится в файле конфигурации. Понятно, что при смене провайдера изменится первая строка в <appSetting>, а при смене БД — вторая строка и только!
4) Перейдем к редактированию Program.cs. В метод Main( ) добавим три оператора:
// Получение поставщика и строки подключения из App.config string dp = ConfigurationManager.AppSettings["provider"]; string cnStr = ConfigurationManager.AppSettings["conStr"]; // Получение генератора поставщика df DbProviderFactory df = DbProviderFactories.GetFactory(dp);
Класс System.Data.Common.DbProviderFactory представляет набор методов для создания экземпляров реализации поставщика для классов источника данных. Метод GetFactory( ) возвращает экземпляр класса. Далее нам будет нужны только генератор поставщика df и строка подключения cnStr.
5) Зададимся целью прочитать содержимое трех таблиц БД Garage: Cars, Drivers, Routes. Для этого нам понадобятся объекты трех классов DbConnection, DbCommand и DbDataReader из библиотеки System.Data.Common. Используем вложенную конструкцию using { }, упомянутую в конце статьи «Сборка мусора и финализаторы«. Напомним, что конструкция упрощает работу с объектами, которые реализуют интерфейс IDisposable. Интерфейс IDisposable содержит один метод .Dispose(), который используется для освобождения ресурсов,
которые захватил объект.
Тогда полный текст Program.cs:
// Генератор поставщиков данных using System; using System.Configuration; using System.Data.Common; namespace ГенераторПоставщиковДанных { class Program { static void Main(string[] args) { // Получение строки подключения и поставщика из App.config string dp = ConfigurationManager.AppSettings["provider"]; string cnStr = ConfigurationManager.AppSettings["conStr"]; // Получение генератора поставщика df DbProviderFactory df = DbProviderFactories.GetFactory(dp); // Получение объекта "подключение" (через df) using (DbConnection cn = df.CreateConnection()) { Console.WriteLine("Объект подключения: " + cn.GetType().Name); cn.ConnectionString = cnStr; cn.Open(); // Создание объекта "команда" (через df) DbCommand cmd = df.CreateCommand(); Console.WriteLine("Объект команды: " + cmd.GetType().Name); cmd.Connection = cn; // cmd.CommandText = strSQL + "TableName"; string strSQL = "Select * From "; // Вывод парка машин с помощью объекта "чтение данных" dr cmd.CommandText = strSQL + "Cars"; using (DbDataReader dr = cmd.ExecuteReader()) { Console.WriteLine("Объект чтения данных: " + dr.GetType().Name); Console.WriteLine("\n Автопарк"); while (dr.Read()) Console.WriteLine("-> ID авто-{0} | ТипАвто-{1} | госномер-{2} | число пассажиров-{3}", dr[0], dr[1], dr[2], dr[3]); } // Вывод списка водителей cmd.CommandText = strSQL + "Drivers"; ; using (DbDataReader dr = cmd.ExecuteReader()) { Console.WriteLine("\n Водители"); while (dr.Read()) Console.WriteLine("-> ID водителя-{0} | Фамилия_имя-{1} | права-{2} | работа/выходной-{3}", dr[0], dr[1], dr[2], dr[3]); } // Вывод маршрутов (водитель-авто) cmd.CommandText = strSQL + "Routes"; using (DbDataReader dr = cmd.ExecuteReader()) { Console.WriteLine("\n Маршруты"); while (dr.Read()) Console.WriteLine("-> ID маршрута-{0} | Номер маршрута-{1} | ID авто-{2} | ID водителя-{3}", dr[0], dr[1], dr[2], dr[3]); } Console.ReadKey(); } } } }
Результат:
Первые три строки содержат информацию по объектам «подключение», «команда» и «чтение данных».
Вывод. Поставленная задача написания независимого (от типа БД) кода выполнена.
В следующей статье «Примеры SQL-запросов. Microsoft SQL Server и язык T-SQL» описаны действия по удалению, вставке и изменению записей в таблицах БД .
NEW: Наш Чат, в котором вы можете обсудить любые вопросы, идеи, поделиться опытом или связаться с администраторами.
![]() |
![]() |
![]() |
![]() |