Настройка параметров подключения и параметров уровня команды на уровне доступа к данным (C#)
Адаптеры таблиц в типизированном наборе данных автоматически подключаются к базе данных, выполняют команды и заполняют таблицу DataTable результатами. Однако бывают случаи, когда мы хотим позаботиться об этих деталях самостоятельно, и в этом руководстве мы узнаем, как получить доступ к параметрам подключения к базе данных и на уровне команд в TableAdapter.
Введение
В рамках серии учебников мы использовали типизированные наборы данных для реализации уровня доступа к данным и бизнес-объектов нашей многоуровневой архитектуры. Как обсуждалось в первом руководстве, таблицы DataTable typed DataSet служат репозиториями данных, в то время как TableAdapters выступают в качестве оболочек для взаимодействия с базой данных для получения и изменения базовых данных. TableAdapters инкапсулируют сложность работы с базой данных и избавляют нас от необходимости писать код для подключения к базе данных, выполнения команды или заполнения результатов в таблицу DataTable.
Однако бывают случаи, когда нам нужно зарыться в глубину TableAdapter и написать код, который работает непосредственно с объектами ADO.NET. Например, в руководстве по переносу изменений базы данных в рамках транзакции мы добавили методы в TableAdapter для начала, фиксации и отката ADO.NET транзакций. Эти методы использовали внутренний, созданный SqlTransaction
вручную объект, назначенный объектам TableAdapter SqlCommand
.
В этом руководстве мы рассмотрим, как получить доступ к параметрам подключения к базе данных и на уровне команд в TableAdapter. В частности, мы добавим в элемент функциональные возможностиProductsTableAdapter
, обеспечивающие доступ к базовым строка подключения и параметрам времени ожидания команды.
Работа с данными с помощью ADO.NET
Microsoft платформа .NET Framework содержит множество классов, предназначенных специально для работы с данными. Эти классы, находящиеся в System.Data
пространстве имен, называются классами ADO.NET . Некоторые классы в ADO.NET зонтично привязаны к конкретному поставщику данных. Поставщик данных можно рассматривать как канал связи, который позволяет передавать информацию между классами ADO.NET и базовым хранилищем данных. Существуют универсальные поставщики, такие как OleDb и ODBC, а также поставщики, специально разработанные для конкретной системы баз данных. Например, хотя можно подключиться к базе данных Microsoft SQL Server с помощью поставщика OleDb, поставщик SqlClient гораздо эффективнее, так как он был разработан и оптимизирован специально для SQL Server.
При программном доступе к данным обычно используется следующий шаблон:
- Установите подключение к базе данных.
- Выполните команду .
- Для
SELECT
запросов работайте с результирующей записью.
Существуют отдельные ADO.NET классы для выполнения каждого из этих шагов. Например, чтобы подключиться к базе данных с помощью поставщика SqlClient, используйте SqlConnection
класс . Чтобы выполнить INSERT
команду , UPDATE
, DELETE
или SELECT
в базе данных, используйте SqlCommand
класс .
За исключением обтекания изменений базы данных в рамках руководства по транзакциям , нам не пришлось самостоятельно писать низкоуровневый код ADO.NET, так как автоматически создаваемый код TableAdapters включает функции, необходимые для подключения к базе данных, выполнения команд, извлечения данных и заполнения этих данных в таблицы DataTables. Однако иногда может потребоваться настроить эти низкоуровневые параметры. В течение следующих нескольких шагов мы рассмотрим, как использовать объекты ADO.NET, используемые внутри TableAdapters.
Шаг 1. Проверка с помощью свойства connection
Каждый класс TableAdapter имеет Connection
свойство , указывающее сведения о подключении к базе данных. Тип данных и ConnectionString
значение этого свойства определяются параметрами, выбранными в мастере настройки TableAdapter. Помните, что при первом добавлении TableAdapter в типизированный набор данных мастер запрашивает источник базы данных (см. рис. 1). Раскрывающийся список на этом первом шаге включает базы данных, указанные в файле конфигурации, а также другие базы данных в Connections данных сервера Обозреватель. Если база данных, которую мы хотим использовать, не существует в раскрывающемся списке, можно указать новое подключение к базе данных, нажав кнопку Создать подключение и указав необходимые сведения о подключении.
Рис. 1. Первый шаг мастера настройки TableAdapter (щелкните для просмотра полноразмерного изображения)
Рассмотрим код свойства TableAdapter Connection
. Как отмечалось в учебнике Создание уровня доступа к данным , мы можем просмотреть автоматически созданный код TableAdapter, перейдя в окно Представление классов, детализировав соответствующий класс, а затем дважды щелкнув имя члена.
Перейдите в окно Представление классов, перейдя в меню Вид и выбрав Представление классов (или нажав клавиши CTRL+SHIFT+C). В верхней части окна Представление классов перейдите к пространству NorthwindTableAdapters
имен и выберите ProductsTableAdapter
класс . Элементы будут отображаться ProductsTableAdapter
в нижней половине представления классов, как показано на рисунке 2. Дважды щелкните свойство, Connection
чтобы просмотреть его код.
Рис. 2. Double-Click свойства Connection в представлении классов для просмотра его автоматически созданного кода
Ниже приведены свойства TableAdapter Connection
и другой код, связанный с подключением:
private System.Data.SqlClient.SqlConnection _connection;
private void InitConnection() {
this._connection = new System.Data.SqlClient.SqlConnection();
this._connection.ConnectionString =
ConfigurationManager.ConnectionStrings["NORTHWNDConnectionString"].ConnectionString;
}
internal System.Data.SqlClient.SqlConnection Connection {
get {
if ((this._connection == null)) {
this.InitConnection();
}
return this._connection;
}
set {
this._connection = value;
if ((this.Adapter.InsertCommand != null)) {
this.Adapter.InsertCommand.Connection = value;
}
if ((this.Adapter.DeleteCommand != null)) {
this.Adapter.DeleteCommand.Connection = value;
}
if ((this.Adapter.UpdateCommand != null)) {
this.Adapter.UpdateCommand.Connection = value;
}
for (int i = 0; (i < this.CommandCollection.Length); i = (i + 1)) {
if ((this.CommandCollection[i] != null)) {
((System.Data.SqlClient.SqlCommand)
(this.CommandCollection[i])).Connection = value;
}
}
}
}
При создании экземпляра класса TableAdapter переменная-член _connection
равна null
. При обращении к свойству Connection
сначала проверяется, был ли _connection
создан экземпляр переменной-члена. Если это не так, InitConnection
вызывается метод , который создает _connection
экземпляр и задает его ConnectionString
свойству значение строка подключения, указанное на первом шаге мастера конфигурации TableAdapter.
Свойство Connection
также можно назначить объекту SqlConnection
. При этом новый SqlConnection
объект связывается с каждым из объектов TableAdapter SqlCommand
.
Шаг 2. Предоставление параметров Connection-Level
Сведения о подключении должны оставаться инкапсулированными в TableAdapter и не должны быть доступны другим уровням в архитектуре приложения. Однако могут возникать ситуации, когда сведения об уровне подключения TableAdapter должны быть доступны или настраиваемы для запроса, пользователя или страницы ASP.NET.
Давайте расширим ProductsTableAdapter
в Northwind
dataSet, чтобы включить ConnectionString
свойство, которое может использоваться уровнем бизнес-логики для чтения или изменения строка подключения, используемых TableAdapter.
Примечание
Строка подключения — это строка, указывающая сведения о подключении к базе данных, например используемый поставщик, расположение базы данных, учетные данные проверки подлинности и другие параметры, связанные с базой данных. Список шаблонов строка подключения, используемых различными хранилищами данных и поставщиками, см. в разделе ConnectionStrings.com.
Как описано в учебнике Создание уровня доступа к данным , автоматически создаваемые классы Typed DataSet можно расширить с помощью разделяемых классов. Сначала создайте вложенную папку в проекте с именем ConnectionAndCommandSettings
под папкой ~/App_Code/DAL
.
Рис. 3. Добавление вложенной папки с именем ConnectionAndCommandSettings
Добавьте новый файл класса с именем ProductsTableAdapter.ConnectionAndCommandSettings.cs
и введите следующий код:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
namespace NorthwindTableAdapters
{
public partial class ProductsTableAdapter
{
public string ConnectionString
{
get
{
return this.Connection.ConnectionString;
}
set
{
this.Connection.ConnectionString = value;
}
}
}
}
Этот разделяемый public
класс добавляет в класс свойство с именем ConnectionString
ProductsTableAdapter
, которое позволяет любому уровню считывать или обновлять строка подключения для базового подключения TableAdapter.
Создав (и сохранив) этот разделяемый ProductsBLL
класс, откройте класс . Перейдите к одному из существующих методов и введите и Adapter
нажмите клавишу точки, чтобы открыть IntelliSense. Вы должны увидеть новое ConnectionString
свойство, доступное в IntelliSense, что означает, что вы можете программно считывать или настраивать это значение из BLL.
Предоставление доступа ко всему объекту connection
Этот разделяемый класс предоставляет только одно свойство базового объекта подключения: ConnectionString
. Если вы хотите сделать весь объект подключения доступным за пределами TableAdapter, можно также изменить Connection
уровень защиты свойства. Автоматически созданный код, рассмотренный на шаге 1, показал, что свойство TableAdapter Connection
помечено как internal
, то есть доступ к нему могут получить только классы в той же сборке. Однако его можно изменить с помощью свойства TableAdapter ConnectionModifier
.
Northwind
Откройте набор данных, щелкните ProductsTableAdapter
в Designer и перейдите к окно свойств. Там вы увидите ConnectionModifier
значение по умолчанию , . Assembly
Чтобы сделать Connection
свойство доступным вне сборки Typed DataSet, измените свойство на ConnectionModifier
Public
.
Рис. 4. Уровень Connection
доступности свойства можно настроить с помощью ConnectionModifier
свойства (щелкните для просмотра полноразмерного изображения)
Сохраните DataSet и вернитесь в ProductsBLL
класс . Как и раньше, перейдите к одному из существующих методов и введите , Adapter
а затем нажмите клавишу точки, чтобы открыть IntelliSense. Список должен содержать Connection
свойство, то есть теперь вы можете программно считывать или назначать любые параметры уровня подключения из BLL.
Шаг 3. Изучение свойств Command-Related
TableAdapter состоит из main запроса, который по умолчанию имеет автоматически созданные INSERT
инструкции , UPDATE
и DELETE
. Это main инструкции INSERT
запроса , UPDATE
и DELETE
реализованы в коде TableAdapter в виде объекта адаптера данных ADO.NET через Adapter
свойство . Как и в случае со свойством Connection
Adapter
, тип данных свойства определяется используемым поставщиком данных. Так как в этих руководствах используется поставщик SqlClient, Adapter
свойство имеет тип SqlDataAdapter
.
Свойство TableAdapter Adapter
имеет три свойства типа SqlCommand
, которые оно использует для выдачи инструкций INSERT
, UPDATE
и DELETE
:
InsertCommand
UpdateCommand
DeleteCommand
Объект SqlCommand
отвечает за отправку определенного запроса в базу данных и имеет такие свойства, как , CommandText
который содержит нерегламентированный sql-оператор или хранимую процедуру для выполнения; и Parameters
, который является коллекцией SqlParameter
объектов . Как мы видели в руководстве По созданию уровня доступа к данным, эти объекты команд можно настроить с помощью окно свойств.
Помимо main запроса, TableAdapter может включать в себя переменное количество методов, которые при вызове отправляют указанную команду в базу данных. Объект команды main запроса и объекты команд для всех дополнительных методов хранятся в свойстве TableAdapter.CommandCollection
Рассмотрим код, созданный ProductsTableAdapter
в Northwind
DataSet для этих двух свойств, а также их вспомогательных переменных-членов и вспомогательных методов:
private System.Data.SqlClient.SqlDataAdapter _adapter;
private void InitAdapter() {
this._adapter = new System.Data.SqlClient.SqlDataAdapter();
... Code that creates the InsertCommand, UpdateCommand, ...
... and DeleteCommand instances - omitted for brevity ...
}
private System.Data.SqlClient.SqlDataAdapter Adapter {
get {
if ((this._adapter == null)) {
this.InitAdapter();
}
return this._adapter;
}
}
private System.Data.SqlClient.SqlCommand[] _commandCollection;
private void InitCommandCollection() {
this._commandCollection = new System.Data.SqlClient.SqlCommand[9];
... Code that creates the command objects for the main query and the ...
... ProductsTableAdapter�s other eight methods - omitted for brevity ...
}
protected System.Data.SqlClient.SqlCommand[] CommandCollection {
get {
if ((this._commandCollection == null)) {
this.InitCommandCollection();
}
return this._commandCollection;
}
}
Код свойств Adapter
и CommandCollection
тесно имитирует Connection
код свойства . Существуют переменные-члены, которые содержат объекты, используемые свойствами . Методы доступа к свойствам get
начинаются с проверки, является ли соответствующая переменная-член .null
Если это так, вызывается метод инициализации, который создает экземпляр переменной-члена и назначает основные свойства, связанные с командой.
Шаг 4. Предоставление параметров Command-Level
В идеале сведения на уровне команд должны оставаться инкапсулированными в уровне доступа к данным. Однако если эти сведения потребуются на других уровнях архитектуры, их можно предоставить через разделяемый класс, как и в случае с параметрами уровня подключения.
Так как TableAdapter имеет только одно Connection
свойство, код для предоставления параметров уровня подключения довольно прост. Изменение параметров на уровне команд немного сложнее, так как TableAdapter может иметь несколько объектов команд — InsertCommand
, UpdateCommand
и DeleteCommand
, а также переменное количество объектов команд в свойстве CommandCollection
. При обновлении параметров на уровне команд эти параметры необходимо распространить на все объекты команд.
Например, представьте, что в TableAdapter были определенные запросы, выполнение которым заняло чрезвычайно много времени. При использовании TableAdapter для выполнения одного из этих запросов может потребоваться увеличить свойство объекта CommandTimeout
команды. Это свойство указывает время ожидания выполнения команды в секундах и значение по умолчанию — 30.
Чтобы разрешить настройку CommandTimeout
свойства bLL, добавьте следующий public
метод в ProductsDataTable
с помощью файла разделяемого класса, созданного на шаге 2 (ProductsTableAdapter.ConnectionAndCommandSettings.cs
):
public void SetCommandTimeout(int timeout)
{
if (this.Adapter.InsertCommand != null)
this.Adapter.InsertCommand.CommandTimeout = timeout;
if (this.Adapter.DeleteCommand != null)
this.Adapter.DeleteCommand.CommandTimeout = timeout;
if (this.Adapter.UpdateCommand != null)
this.Adapter.UpdateCommand.CommandTimeout = timeout;
for (int i = 0; i < this.CommandCollection.Length; i++)
if (this.CommandCollection[i] != null)
this.CommandCollection[i].CommandTimeout = timeout;
}
Этот метод можно вызвать из BLL или уровня презентации, чтобы задать время ожидания команды для всех проблем с командами экземпляром TableAdapter.
Примечание
Свойства Adapter
и CommandCollection
помечены как private
, то есть доступ к им можно получить только из кода в TableAdapter. Connection
В отличие от свойства, эти модификаторы доступа не настраиваются. Таким образом, если необходимо предоставить свойства уровня команд другим уровням архитектуры, необходимо использовать описанный выше подход к разделяемым классам, чтобы предоставить public
метод или свойство, которое считывает или записывает private
в объекты команд.
Сводка
Адаптеры TableAdapters в типизированном наборе данных служат для инкапсуляции сведений о доступе к данным и сложности. Используя TableAdapters, нам не нужно беспокоиться о написании ADO.NET кода для подключения к базе данных, выполнения команды или заполнения результатов в таблицу DataTable. Все это обрабатывается автоматически для нас.
Однако в некоторых случаях нам может потребоваться настроить низкоуровневые ADO.NET особенности, например изменить строка подключения или значения по умолчанию для подключения или времени ожидания команды. TableAdapter имеет автоматически созданные Connection
свойства , Adapter
и CommandCollection
, но по умолчанию они имеют значение internal
или private
. Эти внутренние сведения можно предоставить, расширив TableAdapter с помощью разделяемых классов для включения public
методов или свойств. Кроме того, модификатор доступа к свойству TableAdapter Connection
можно настроить с помощью свойства TableAdapter s ConnectionModifier
.
Счастливого программирования!
Об авторе
Скотт Митчелл( Scott Mitchell), автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с веб-технологиями Майкрософт с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Sams Teach Yourself ASP.NET 2.0 в 24 часах. Он может быть доступен в mitchell@4GuysFromRolla.com. или через его блог, который можно найти по адресу http://ScottOnWriting.NET.
Особая благодарность
Эта серия учебников была рассмотрена многими полезными рецензентами. Ведущим рецензентом этого руководства были Бернадет Ли, Срен Джейкоб Лауритсен, Тереса Мерфи и Хилтон Гейзенов. Хотите просмотреть предстоящие статьи MSDN? Если да, опустите мне строку на mitchell@4GuysFromRolla.com.