Поделиться через


Настройка параметров подключения и параметров уровня команды на уровне доступа к данным (C#)

Скотт Митчелл

Скачать в формате PDF

TableAdapters в типизированном наборе данных автоматически заботятся о подключении к базе данных, выполнении команд и заполнении таблицы данных результатами. Однако бывают случаи, когда мы хотим сами позаботиться об этих деталях. В этом руководстве мы узнаем, как получить доступ к настройкам уровня подключения и уровня команд в TableAdapter.

Введение

В серии учебников мы использовали типизированные наборы данных для реализации уровня доступа к данным и бизнес-объектов нашей многоуровневой архитектуры. Как описано в первом руководстве, таблицы данных набора данных Typed служат хранилищами информации, в то время как TableAdapters выполняют роль оболочек для взаимодействия с базой данных с целью извлечения и изменения базовых данных. TableAdapters инкапсулирует сложность работы с базой данных и сохраняет нас от необходимости писать код для подключения к базе данных, выдачи команды или заполнения результатов в DataTable.

Тем не менее, бывают случаи, когда нам нужно углубиться в глубины TableAdapter и писать код, который работает непосредственно с объектами ADO.NET. В руководстве «Оболочка модификаций базы данных в транзакции», например, мы добавили методы в TableAdapter для начала, фиксации и отката транзакций ADO.NET. Эти методы использовали внутренний, вручную созданный SqlTransaction объект, который назначался объектам SqlCommand TableAdapter.

В этом руководстве мы рассмотрим, как получить доступ к параметрам подключения к базе данных и уровня команд в 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 класс. Чтобы выполнить INSERTUPDATEDELETEкоманду или SELECT команду для базы данных, используйте SqlCommand класс.

За исключением руководства «Обрамление изменений базы данных в транзакцию», нам не пришлось самостоятельно писать низкоуровневый код ADO.NET, поскольку автоматически созданный код TableAdapters включает функции, необходимые для подключения к базе данных, выполнения команд, извлечения данных и заполнения этими данными DataTables. Однако может возникнуть время, когда необходимо настроить эти низкоуровневые параметры. На следующих нескольких шагах мы рассмотрим, как подключиться к объектам ADO.NET, используемым внутри tableAdapters.

Шаг 1. Изучение свойства подключения

Каждый класс TableAdapter имеет Connection свойство, указывающее сведения о подключении к базе данных. Тип данных этого свойства и значение ConnectionString определяются выбранными в мастере настройки TableAdapter. Помните, что при первом добавлении TableAdapter в типизированный набор данных этот мастер запрашивает у нас источник базы данных (см. рис. 1). Раскрывающийся список в этом первом шаге включает эти базы данных, указанные в файле конфигурации, а также любые другие базы данных в подключениях к данным обозревателя серверов. Если база данных, которую мы хотим использовать, не существует в раскрывающемся списке, можно указать новое подключение к базе данных, нажав кнопку "Создать подключение" и указав необходимые сведения о подключении.

Первый шаг мастера настройки TableAdapter

Рис. 1. Первый шаг мастера настройки TableAdapter (щелкните, чтобы просмотреть изображение полного размера)

Давайте уделим момент, чтобы тщательно рассмотреть код для свойства TableAdapter Connection. Как отмечалось в руководстве по созданию уровня доступа к данным , можно просмотреть автоматически созданный код TableAdapter, перейдя в окно представления классов, свернув до соответствующего класса, а затем дважды щелкнув имя члена.

Перейдите в окно представления классов, перейдя в меню "Вид" и выбрав представление классов (или введя клавиши CTRL+SHIFT+C). В верхней половине окна представления классов выполните детализацию до NorthwindTableAdapters пространства имен и выберите ProductsTableAdapter класс. Это отобразит элементы ProductsTableAdapter в нижней половине Class View, как показано на рис. 2. Дважды щелкните на свойстве Connection, чтобы просмотреть его код.

Double-Click свойство подключения в представлении классов для просмотра его автоматически созданного кода

Рис. 2. Double-Click свойство подключения в представлении классов для просмотра автоматически созданного кода

Свойство 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 .

Раскрытие настроек Connection-Level

Сведения о подключении должны оставаться инкапсулированными в TableAdapter и недоступны для других слоев архитектуры приложения. Однако могут возникнуть сценарии, когда сведения о уровне подключения TableAdapter должны быть доступны или настраиваемы для страницы запроса, пользователя или ASP.NET.

Давайте расширим ProductsTableAdapter в Northwind наборе данных, чтобы добавить свойство ConnectionString, которое уровень бизнес-логики сможет использовать для чтения или изменения строки подключения, применяемой TableAdapter.

Замечание

Строка подключения — это строка, указывающая сведения о подключении к базе данных, например поставщик, расположение базы данных, учетные данные проверки подлинности и другие параметры, связанные с базой данных. Список шаблонов строк подключения, используемых различными хранилищами данных и поставщиками, см. ConnectionStrings.com.

Как описано в руководстве по созданию уровня доступа к данным , автоматически созданные классы Набора данных можно расширить с помощью частичных классов. Сначала создайте новую вложенную папку в проекте с именем ConnectionAndCommandSettings, поместив её внутрь папки ~/App_Code/DAL.

Добавление подпапки с именем ConnectionAndCommandSettings

Рис. 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.

Раскрытие всего объекта соединения

Этот частичный класс предоставляет только одно свойство базового объекта подключения: ConnectionString Если вы хотите сделать весь объект подключения доступным за пределами TableAdapter, можно также изменить Connection уровень защиты свойства. Автоматически созданный код, который мы рассмотрели на шаге 1, показал, что свойство TableAdapter Connection помечено как internal, что означает, что доступ к нему можно получить только классами в той же сборке. Это можно изменить, однако, с помощью свойства TableAdapter ConnectionModifier .

Откройте "набор данных" Northwind, щелкните на ProductsTableAdapter в Конструкторе и перейдите в окно "Свойства". Там вы увидите, что ConnectionModifier установлен на значение по умолчанию Assembly. Чтобы сделать Connection свойство доступным вне сборки Typed DataSet, измените свойство ConnectionModifier на Public.

Уровень доступности свойства подключения можно настроить с помощью свойства ConnectionModifier

Рис. 4.Connection Уровень специальных возможностей свойства можно настроить с помощью ConnectionModifier свойства (щелкните, чтобы просмотреть изображение полного размера)

Сохраните набор данных и вернитесь к классу ProductsBLL . Как и раньше, перейдите к одному из существующих методов и введите Adapter, а затем нажмите клавишу точки, чтобы открыть IntelliSense. Список должен содержать Connection свойство, что означает, что теперь можно программно считывать или назначать любые параметры уровня подключения из BLL.

TableAdapter состоит из основного запроса, который по умолчанию имеет автоматически созданные операторы INSERT, UPDATE, и DELETE. Эти основной запрос и 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. Как мы узнали в руководстве по созданию уровня доступа к данным , эти объекты команд можно настроить в окне "Свойства".

В дополнение к основному запросу TableAdapter может включать переменное количество методов, которые при вызове отправляют указанную команду в базу данных. Основной объект команды запроса и объекты команд для всех дополнительных методов хранятся в свойстве TableAdapter CommandCollection .

Рассмотрим код, созданный ProductsTableAdapter в Northwind наборе данных для этих двух свойств, их член-переменных и вспомогательных методов:

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 ConnectionModifier .

Счастливое программирование!

Сведения о авторе

Скотт Митчелл, автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с технологиями Microsoft Web с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга — Sams Teach Yourself ASP.NET 2.0 за 24 часа. С ним можно связаться по адресу mitchell@4GuysFromRolla.com.

Особое спасибо кому

Эта серия учебников была проверена многими полезными рецензентами. Ведущие рецензенты для этого руководства были Бернадетт Ли, Сёрен Якоб Лауритсен, Тереса Мерфи и Хилтон Гейзеноу. Хотите просмотреть мои предстоящие статьи MSDN? Если да, напишите мне на mitchell@4GuysFromRolla.com.