Доступ к данным Перевод Александра Гладченко (надеюсь, корпорация Микрософт не будет в обиде) Доступ к данным с помощью ADO.NET 1. Введение2. Доступ к данным с помощью ADO.NET 3. Компоненты ADO.NET и объектная модель 4. Использование Managed provider 5. Использование DataSet 6. Использование DataTable 7. Работа с данными в таблицах ADO.NET 8. Свод событий ADO.NET Доступ к XML и реляционным данным 1. Краткий обзор2. Чтение и запись Xml 3. Исполнение Document Object Model (DOM) 4. XmlDataDocument и Dataset 5. Избранные файлы System.Xml Доступ к данным средствами ASP.NET 1. Краткий обзор2. Связывание (Binding) SQL данных с Repeater Control 3. Связывание SQL данных с DataList Control 4. Связывание SQL данных с DataGrid Control 5. Вставка данных в SQL базу данных 6. Обновление данных в базе 7. Удаление данных из базы 8. Сортировка данных Материалы этой статьи относятся к бэтта версии продукта и могут не соответствовать окончательному варианту. Кроме того, у автора перевода пока не нашлось времени опробовать и протестировать все приведённые здесь примеры, поэтому Вы можете использовать их только на свой страх и риск. Автор не несёт ответственности ни за одну строчку предлагаемой Вам документации. Будьте осторожны! Поскольку автор не является профессиональным переводчиком, возможны не точности перевода, так что не спешите взваливать вину за неудачное использование предлагаемой Вам информации на замечательную команду разработчиков Микрософт. Возможно, просто я не до конца вник в их сленг или чего-то недопонял. Так что, не воспринимайте всё на веру. Для обсуждения этой документации и для высказывания всех замечаний и предложений, а также для разного рода комментариев и отзывов, создан специальный топик, в разделе форума, посвящённом обсуждению материалов на сервере. Очень надеюсь на вашу критику и отзывы.Обсуждение документации: "Доступ к данным с помощью ADO.NET" | |
1. Введение Работа с данными стала главной задачей современного
программного обеспечения, как автономных, так и сетевых
прикладных программ. Технология ADO.NET предлагает решение
многих проблем, связанных с доступом к данным. ADO.NET -
эволюционное развитие ActiveX Data Objects (далее ADO). Это -
модель программирования на основе стандартов для создания
распределенного, прикладного программного обеспечения,
предназначенного для совместного использования данных
(data-sharing). ADO.NET имеет несколько существенных
преимуществ относительно предыдущих версий ADO, а также других
компонент доступа к данным. Эти преимущества относятся к
следующим категориям: Interoperability (способность к
взаимодействию), Maintainability (надёжность), Programmability
(программируемость), и Performance (эффективность). Ниже, мы
более подробно рассмотрим эти преимущества. Для прикладных
программ на основе ASP.NET предусмотрена возможность
использования технологии ADO.NET, что позволяет обращаться к
данным по сети или через Веб. Поэтому, совместное
использование ASP.NET и ADO.NET также будет предметом нашего
рассмотрения. | |
2.
Доступ к данным с помощью ADO.NET
2.1. Краткий обзор ADO.NET 2.2. Сравнение ADO и ADO.NET 2. Доступ к данным с помощью ADO.NET ADO.NET является преемником Microsoft ActiveX Data Objects (ADO). Это W3C стандартизированная модель программирования для создания распределенных прикладных программ, нацеленных на совместное использование данных. Подобно ADO, ADO.NET является программным интерфейсом (API) для прикладного программного обеспечения, позволяющим обращаться к данным и другой информации. ADO.NET поддерживает такие современные требования, как создание клиентского интерфейса к базам данных на фронтальном уровне и на уровне промежуточного слоя объектов клиентских приложений, инструментальных средств, языков программирования или Internet браузера. 2.1. Краткий обзор ADO.NET Технология ADO.NET разработана на основе промышленных
стандартов. ADO.NET, подобно ADO, обеспечивает интерфейс
доступа к OLE DB - совместимым источникам данных, таким, как
Microsoft SQL Server 2000. Прикладные программы, позволяющие
пользователям совместно использовать данные, могут
использовать ADO.NET для подключения к источниками данных, а
также для поиска, управления, и модификации этих данных.
Также, прикладные программы (далее ПП) могут использовать OLE
DB для управления данными, хранящимися в не относительных
форматах, таких, как Microsoft Excel. ADO.NET - эволюционное развитие ADO. Самый простой путь
быстрого понимания преимуществ ADO.NET состоит в сравнении с
ADO.
| ||||||||||||||||||||||||||||
3.
Компоненты ADO.NET и объектная модель
3.1. DataSet 3.1.1. Объект TablesCollection 3.1.2. Объект RelationsCollection 3.1.3. ExtendedProperties 3.2. Managed providers 3.3. Microsoft ADO.NET managed providers 3.4. Поддерживаемые базы данных и OLE DB провайдеры 3. Компоненты ADO.NET и объектная модель
Есть две основные части ADO.NET. «DataSet» - который передаётся между компонентами ADO.NET и управляемые провайдеры (Managed Providers). 3.1. DataSet Объект DataSet является самым важным в ADO.NET. DataSet это простая резидентная база данных, которая обеспечивает непротиворечивую модель программирования независимо от источника данных. DataSet представляет собой законченный набор данных, включая связанные таблицы, ограничения, и отношения между таблицами. Модель объекта DataSet представлена ниже. DataSet Объект DataSet используют для управления содержанием набора данных. Методы и объекты в DataSet совместимы с реляционной моделью баз данных. 3.1.1. Объект TablesCollection ADO.NET DataSet представляет собой совокупность одной или
более таблиц, представленных объектами DataTable. Объект
TablesCollection содержит все объекты DataTable, имеющиеся в
DataSet. 3.1.2. Объект RelationsCollection Типичный набор данных (DataSet) содержит отношения,
определяемые объектом RelationsCollection. Отношения,
представляемые объектом DataRelation, сопоставляют строки в
одной таблице, строкам в другой таблице данных. Это работает
аналогично отношениям foreign-key в реляционной базе данных.
DataRelation идентифицирует соответствие столбцов в двух
таблицах DataSet. 3.1.3. ExtendedProperties Объект ExtendedProperties содержит введённую информацию о пользователе, пароли или о времени, когда данные объекта DataSet должны быть обновлены. 3.2. Managed providers Managed provider устанавливает подключения между DataSet и источниками данных, например, базой данных SQL Server. Managed providers состоит из набора интерфейсов, которые осуществляют доступ к источнику данных. Существует три исполняемых компонента: - Подключение (Connection), команды, и параметры
обеспечивают интерфейс между источником данных и объектом
DataSet. Интерфейс DataSetCommand определяет столбец и
отображения таблицы, а также загружает DataSet. Раньше, чаще всего использовалась двухъярусная архитектура обработки данных, которая основывалась на подключении. В настоящее время, поскольку обработка данных все более тяготеет к многоярусной архитектуре, программисты переключают своё внимание на офлайновые подходы, обеспечивающие лучшую масштабируемость для прикладных программ. Одним из самых важных компонент ADO.NET, обеспечивающих современные требования, является DataSetCommand. Он загружает DataSet и обеспечивает мост между объектом DataSet и его исходным источником данных для целей обработки и сохранения информации. Осуществляется это посредством вызовов соответствующих SQL команд на источнике данных. Объектная модель для Managed provider, отображающая уровни между DataSet и источником данных, представлена ниже.
Как Вы видите, объект DataSetCommand определяет четыре
базовые метода. Эти методы/команды обеспечивают create, read,
update и delete функции для определенного DataTable в пределах
DataSet. 3.3. Microsoft ADO.NET managed providers Микрософт выпускает два managed providers для ADO.NET. SQL managed provider.
Является посредником между таблицей в пределах DataSet и таблицей или представлением базы данных SQL Server (версия 7.0 и выше). Объект SQLDataSetCommand является посредником связи между таблицей DataSet и таблицей или представлением сервера баз данных. ADO managed provider. Является посредником связи между таблицей в пределах DataSet и таблицей или представлением в любом источнике данных, для которого имеется провайдер OLEDB. Объект ADODataSetCommand поддерживает связь между таблицей DataSet и таблицей или представлением в источнике данных. Оба они поддерживают подключение, команды и параметры для
соответствующих источников данных, а также инструментарий
класса DataSetCommand, который обеспечивает уровень
отображения между источником данных и DataSet. Также, они
поддерживают IDataReader, который предоставляет средства
high-performance доступа к данным. 3.4. Поддерживаемые базы данных и OLE DB
провайдеры ADO managed provider проектировался, чтобы работать с большинством OLEDB провайдеров. Следующие провайдеры были проверены и работают с ADO .NET:
Примечание: SQL managed provider поддерживает SQL Server
версии 7.0 и выше. | ||||||||||||||||
4.
Использование Managed provider
4.1. Управление подключениями 4.2. Формат строки подключения – ADOConnection 4.3. Формат строки подключения – SQLConnection 4.4. Команды 4.5. DataReader 4.6. Использование хранимых процедур в команде 4.7. Создание простых DataSetCommand 4.8. Обновление базы данных с помощью DataSetCommand и DataSet 4.9. Определение отображений таблиц и столбцов 4.10. Mapping/Changing отображение столбцов во время исполнения 4.11. Использование параметров DataSetCommands 4.12. Параметры Input/Output и возвращаемые значения 4.13. Объединённое подключение (Connection Pooling) 4.13.1. Определение подкласса SQLConnection 4.13.2. Включение в код строк, которые организуют объединенное подключение 4.13.3. Подключение Microsoft.ComServices.dll 4.13.4. Конфигурирование объединения компонент 4.13.5. Поддержка транзакций 4.14. Команды генерируемые автоматически 4.14.1. Правила организации команды Update 4.14.2. Правила организации команды Insert 4.14.3. Ограничения логики механизма AutoGen 4.15. Добавление и удаление событий SQL Managed provider 4.15.1. Обвальные исключения, порождённые обработчиком событий< 4.15.2. Семантика добавления и удаления событий 4.15.3. Сравнение делегатов при добавление и удаление событий< 4. Использование Managed provider Команды, подключение, и DataReader представляют основные элементы модели ADO.NET. 4.1. Управление подключениями Чтобы соединяться с источником данных, используйте любой из
двух объектов Connection, входящий в состав .NET Framework, и
который поддерживается Microsoft: SQLConnection или
ADOConnection. - SQL Managed Provider – System.Data.SQL Следующий код демонстрирует создание и открытие подключения к базе данных SQL Server: SQLConnection [VB] [C#] ADOConnection [VB] [C#] Объекты ADO и SQL Connection обеспечивают многие из
свойств, которые Вы привыкли использовать в ADO. 4.2. Формат строки подключения –
ADOConnection Для ADO managed provider, формат строки подключения идентичен формату строки подключения, используемому в ADO. 4.3. Формат строки подключения – SQLConnection SQL managed provider поддерживает формат строки подключения, который подобен формату строки подключения ADO. Для определения допустимых имён и значений, см. свойства SQLConnection.ConnectionString в справочниках .NET Framework SDK. 4.4. Команды Обеспечив подключение, Вы должны затем иметь возможность выполнять инструкции, предназначенные базе данных. Самый простой и наиболее прямой способ использовать объекты ADO и SQL Command. Следующий код демонстрирует как это делается: ADOCommand [VB] [C#] SQLCommand [VB] [C#] Дополнительный объект должен быть создан до запроса метода команды Execute с объектом в качестве параметра. ADO [VB] [C#] SQL [VB] [C#] Пример объявляет переменную, которая будет принадлежать иллюстрируемому SQLDataReader, возвращенный как параметр метода execute последней команды. 4.5. DataReader Когда обрабатывается большое количество данных, отвлечение
на это памяти может стать проблемой или узким местом
производительности. Например, чтение 10000 строк из базы
данных заставляет DataTable распределять и удерживать память
для всех 10000 строк и на весь срок жизни таблицы. Если 1000
пользователей обратятся с таким запросом к одному серверу и в
одно и то же время, использование памяти может стать
проблемой. [VB] [C#] DataReader также поддерживает, ряд Get методов, которые позволяют обращаться к значениям полей, таким, как время. Например: GetDataTime, GetDouble, GetGuid, GetInt32, GetStream. 4.6. Использование хранимых процедур в команде Когда Вам нужно возвратить только одну строку, вероятно,
самый быстрый путь использовать хранимую процедуру с выходными
параметрами. При использовании Microsoft SQL Server, или
других баз данных, имеющих процедуры, параметры могут
использоваться, чтобы отобрать единственную строку.
Использование параметров работает также как в ADO. Вы можете
передавать строку в команде, или использовать совокупность
параметров. [VB] [C#] При использовании следующего кода, будет создана команда, которая выполняет вызов хранимой процедуры по имени «GetCompanyName». Эта хранимая процедура объявлена в SQL Server как: CREATE PROCEDURE
GetCompanyName Чтобы выполнять эту хранимую процедуру, выполните следующие
шаги: SQL [VB] [C#] ADO [VB] [C#] Создайте команду, как уже писалось выше, для организации Вашего подключения. Установите с помощью конструктора класса в свойстве команды commandtext - имя хранимой процедуры. ADOCommand myCommand =
new ADOCommand("GetCompanyName",
myConnection); Другой вариант состоит в том, чтобы просто создать команду, затем назначать подключение и commandtext через их вспомогательные свойства. ADOCommand myCommand =
new ADOCommand(); Затем, создайте два параметра объекта, и добавьте их к совокупности параметров команды. SQL SQLParameter workParam
= null; ADO workParam =
myCommand.Parameters.Add("@CustomerID", ADODBType.Char,
5); Здесь, Вы делаете три вещи: создаёте и добавляете
параметры, устанавливаете назначение параметра, и
устанавливаете значение для входного параметра. [VB] [C#] Последнее, важное замечание. Обратите внимание на последний блок. Последний блок инструкции, это уловка, которая всегда гарантированно будет выполнена, независимо от того, будет ли получено исключение. [VB] [C#] Работая с подключением и DataReaders, Вы всегда должны
использовать этот последний, завершающий соединение блок,
чтобы гарантировать, что если что – ни будь потерпит неудачу,
соединение всё равно будут закрыты. 4.7. Создание простых DataSetCommand Основная функция DataSetCommand состоит в получении данных
из источника и загрузка их в DataTable из состава DataSet. Для
этого, DataSetCommand необходимо всего две вещи: организация
подключения (connection) и выполнение команды Select. [VB] [C#] Представленный выше код выполняет следующее: 1. Создает новый объект ADOConnection, использующий строку
подключения. Другая возможность получения необходимого результата могла состоять в том, чтобы создать экземпляры каждого из объектов и затем настроить DataSetCommand через её свойства. [VB] [C#] Эта DataSetCommand может использоваться, чтобы заполнить
DataTable принадлежащую DataSet. Как ADO, так и SQL
DataSetCommand объекты используют метод FillDataSet, имеющий
два параметра: экземпляр DataSet и имя таблицы источника.
Экземпляр DataSet представляет DataSet для заполнения, а имя
таблицы источника идентифицирует таблицу внутри DataSet. [VB] [C#] Результатом вызова метода FillDataSet станет заполнение
таблицы "Customers" в DataSet. Но Вы можете спросить: «Почему
таблица Customers вошла в DataSet, хотя она фактически не была
создана до выполнения метода FillDataSet?». 4.8. Обновление базы данных с помощью DataSetCommand и DataSet ADO и SQL DataSetCommand объекты обеспечивают метод Update,
позволяющий переносить изменения в DataSet назад в базу
данных. Метод Update, подобно методу FillDataSet, использует
экземпляр DataSet и имя таблицы источника. Экземпляр DataSet –
это DataSet, который содержит изменения, внесённые Вами, в то
время как исходное имя таблицы идентифицирует DataTable, в
которой содержатся изменения. [VB] [C#] Пожалуйста помните, что "removing" отличается от "deleting". Если Вы фактически использовали "remove" для строки из выборки, DataSetCommand не будет видеть эту строку, когда Вы применяете метод Update для DataSet. Таким образом, не будет выполняться никакая команда для этой строки. Однако, если строка отмечена как "deleted", команда удаления будет исполнена. 4.9. Определение отображений таблиц и столбцов Вы можете вносить изменения в таблицу с целью её заполнения или переноса изменений и схемы в DataSet, для чего понадобится задать отображение таблицы или столбца. Такое отображение таблиц (master mapping) обеспечивает взаимосвязь между данными, возвращёнными из таблицы в базе данных, и DataTable внутри DataSet. Следующий пример показывает, как создать отображение таблицы, используя Table как исходное имя таблицы и MyAuthors как имя DataTable. [VB] [C#] Это отображение таблицы создает виртуальную связь (ссылку)
между таблицей в базе данных (указанной в инструкции Select и
заданной по умолчанию с именем Table) и таблицы в DataSet,
называемой MyAuthors. [VB] [C#] Для ADO и SQL DataSetCommand объектов, когда методы Update или FillDataSet вызываются без указания таблицы источника, DataSetCommand ищет отображение к таблице источнику по имени Table. В таком случае, имя таблицы из DataSet запрашивается у отображения и далее используется это имя, причём, если таблица с таким именем не находится из числа принадлежащих объекту DataSet, к совокупности таблиц добавляется новая таблица, для которой используя указанное имя. [VB] [C#] В представленном выше примере, создаётся отображение
таблицы, которая становится заданной по умолчанию с именем
Table. Когда Вы вызываете методы Update или FillDataSet без
имени таблицы источника, DataSetCommand будет использовать это
отображение. [VB] [C#] Вызов метода FillDataSet, применяется к экземпляру DataSet
и использует ссылки к таблице источника. DataSetCommand
просматривает совокупность TableMappings, чтобы определить,
существует ли отображение к заданному имени таблицы источника.
Если это так, используется найденное отображение, чтобы
построить и заполнить таблицу. Но если исходное имя таблицы не
существует в совокупности, эта таблица сразу же будет создана
в совокупности TableMappings. 4.10. Mapping/Changing отображение столбцов во время исполнения Даже притом, что TableMappings совокупность обеспечивает
достаточно сильный механизм для отображения таблиц и столбцов
в базе данных в таблицы и столбцы DataSet, может возникнуть
необходимость динамического изменения этого отображения во
время исполнения. Поддержкой такой возможности занимается
SchemaMapping. Вы можете обращаться к внутренним структурам
отображения DataSetCommand и делать там необходимые
изменения. SELECT @@IDENTITY Обычно, это породило бы ошибку при попытке загрузить
результат в DataSet, так как DataSet требует, чтобы все
столбцы имели имена. Чтобы отобразить столбец без имени в
столбец DataTable, Вы можете использовать декларацию события
SQLSchemaMapping для объекта SQLDataSetCommand (для события
ADOSchemaMapping, это будет соответственно объект
ADODataSetCommand) чтобы обойтись без имени столбца. [VB] [C#] 4.11. Использование параметров DataSetCommands Для установки DataSetCommand, в целях использования
параметризованного запроса или хранимой процедуры для метода
Update, делайте то же самое, что Вы делали бы, чтобы
использовать инструкции этого типа с Command Object.
Единственное дополнение, которое Вы должны рассмотреть, это
rowversion, который Вы будете использовать в каждом параметре.
string insertSQL =
"INSERT INTO [Customers]([CustomerID],
[CompanyName], Вы должны установить шесть элементов для каждого из параметров. Для трёх первых, используйте метод Parameters.Add или конструктор параметров. Ниже показано, как установить для имени параметра «CustomerID» из совокупности параметров - тип данных, и их размер: workParam = workCommand.Parameters.Add("CustomerID", ADODBType.WChar, 5); Для типов, определяющих свойства и выраженных целым числом, размер включить ненужно, или можно просто установить использование заданного по умолчанию размера. workParam = workCommand.Parameters.Add("FldItemID", ADODBType.Integer, 4); Также, для элемента должно быть установлено направление (Input – Output) параметра: workParam.Direction = ParameterDirection.Input; Направления параметра допускает следующие возможные варианты параметров настройки:
Последние два элемента, которые должны быть установлены - SourceColumn и SourceVersion. SourceColumn сообщает DataSetCommand какой из столбцов в таблице будет обеспечивать её значение. Чтобы устанавливать его, назначьте имя столбца, как это поддерживается в таблице. workParam.SourceColumn = "CustomerID"; SourceVersion определяет, от какой версии DataRow - DataSetCommand должен передать значение. Параметры для этого из DataRowVersion перечислены в таблице:
Заметьте, что в инструкции update (определенной выше) столбец CustomerID используется в двух местах (в update и в предложении where). При использовании этой инструкции, чтобы изменить первичное значение «ALFKI» на «AAAAA», Вы должны иметь возможность исполнить следующее действие: «Update строки, чей первичный ключ в настоящее время принимает значение ALFKI, а должно получится значение первичного ключа AAAAA» (Update the row whose primary key is currently ALFKI to have a primary key of AAAAA). Таким образом, в этом примере, Вы заставляете все параметры в update использовать DataRowVersion.Current. Но Вы должны устанавливать параметры предложения where, чтобы использовать DataRowVersion.Original. ADOParameter workParam
= null; workParam = workCommand.Parameters.Add("oldCustomerID",
ADODBType.WChar, 5); 4.12. Параметры Input/Output и возвращаемые значения При использовании хранимых процедур, в дополнение к параметрам ввода и вывода, Вы можете иметь возвращаемые значения (return values). ADO.NET обрабатывает возвращаемые из хранимой процедуры значения точно так же, как входные значения. Следующая хранимая процедура получает customerID как входной параметр, возвращает companyname как выходной параметр, и имеет возвращаемое значение. CREATE PROCEDURE
GetCompanyName Представленный ниже пример показывает код, который вызывает хранимую процедуру GetCompanyName: [VB] [C#] Единственное требование, для получения возвращаемое из хранимой процедуры значение необходимо указать направление первого параметра (в совокупности параметров), которое должно обозначать вывод (Output). 4.13. Объединённое подключение (Connection Pooling) Для разработки высокопроизводительных приложений, Вы должны использовать объединенное подключение. При использовании ADO Managed Provider, объединенное подключение не используется, т.к. ADO Managed Provider создаёт его автоматически. Для организации объединенного подключения SQL Managed Provider использует службу Windows 2000 Component Services, и Вы должны для этого следовать указанным ниже шагами: 1. Определите подкласс SQLConnection, используя код,
представленный ниже. 4.13.1. Определение подкласса SQLConnection Следующий код определяет подкласс для класса SQLConnection. Используйте Guidgen.exe, чтобы получить новый Guid (FD5ABffd-D026-4684-8515-2BB5184E8991 в представленной ниже выборке). [ConstructionEnabled(default="Server=servername
…"] //
required here or in gui 4.13.2. Включение в код строк, которые организуют объединенное подключение. Класс объединённого подключения используется очень похоже на обычный SQLConnection, как это показано в следующем примере кода: IReader
iReader; Модель объединённого подключения та же самая, что и у не объединенных подключений. Однако, очень важно вызывать Close, при завершении объединённого подключения и возврате назад в объединение. 4.13.3. Подключение Microsoft.ComServices.dll COM+ Services DLL должен быть подключён, чтобы обеспечить поддержку объединения. 4.13.4. Конфигурирование объединения компонент Хотя объединенный объект подключения может быть жёстко конфигурирован, через установку атрибут во времени компиляции, часто желательно изменять поведение объекта после того, как приложение было развернуто. Чтобы это обеспечить, такие атрибуты, как строка подключения (также называемая строкой конструкции) и транзакционные ограничения могут быть установлены в Component Services из Administrative Tools. 4.13.5. Поддержка транзакций Одно из преимуществ механизма объединения это то, что
обеспечивается поддержка управления поведением транзакционного
механизма. SQL Managed provider определяет, имеет ли текущий
контекст распределенную транзакцию, связанную с задачей, и
если это так, обеспечит автоматическую организацию транзакции.
Вы можете управлять поведением транзакционным механизмом
объединенного подключения во времени компиляции с помощью
TransactionAttribute или во время выполнения с помощью
Component Services из Administrative Tools. 4.14. Команды генерируемые автоматически Для простых модификаций, SQL и ADO Managed provider
обеспечивают автоматическую генерацию команд (AutoGen). Если
свойства команды delete, insert или update не установлены
пользовательским, это механизм автоматически генерирует
отсутствующие инструкции, чтобы создать полнофункциональный
запрос. Автоматическая генерация команд вызывается, если для
объекта DataSetCommand любое из указанных свойств не
установлено. 4.14.1. Правила организации команды Update Автоматически сгенерированная команда update обновляет значения всех столбцов кроме столбцов non-updateable (например, в случае тождеств или выражений). Команда имеет следующий формат: UPDATE Rules for Generating Delete Commands DELETE FROM 4.14.2. Правила организации команды Insert При автоматической генерации, команда insert вставляет значения во всех столбцах, которые являются updateable (исключая столбцы identifies, expressions или timestamps). Формат команды будет следующий: INSERT INTO 4.14.3. Ограничения логики механизма AutoGen Следующие ограничения относятся к автоматически
генерируемым командам: 4.15. Добавление и удаление событий SQL Managed provider Ниже перечислены события ADODataSetCommand класса. Для дополнительной информации, см. ссылку на ADODataSetCommand класс.
4.15.1. Обвальные исключения, порождённые обработчиком событий Избегите обвальных исключений (throwing exceptions) при обработке методов в коде, вызывающем событие. Если исключение распространяется от обработчика до кода вызова, ни один ожидающий это событие процесс не будет уведомлен относительно этого события. Эта проблема скрыта внутри .NET Framework. 4.15.2. Семантика добавления и удаления событий Вы в любое время можете добавлять или удалять делегата из
списка делегатов, получающих специальное событие. Это будет
происходить непосредственно в течение выполнения функции
отзыва. Отзыв может быть добавлен в список любое количество
раз. Если он добавлен больше чем единожды, он будет вызываться
больше чем один раз. 4.15.3. Сравнение делегатов при добавление и удаление событий Эквивалентность делегатов при добавлении и удалении событий полностью зависит от выполнения System.Delegate. При добавлении и удалении делегатов к событиям, нет необходимости поддержать ссылку делегата. Следующий код демонстрирует это: conn.InfoMessageEvent
+= new
InfoMessageEventHandler(myStaticFunc); Два делегата рассматриваются равными даже в том случае,
если они представляют два различных экземпляра.
Равенство/эквивалентность двух делегатов А и B достигается:
| |||||||||||||||||||||||||||||||||
5.
Использование DataSet
5.1. Использование DataSet с существующими данными 5.2. Создание DataSet программным путём 5.3. Добавление DataTable в DataSet 5.4. Добавление отношений между двумя таблицами 5.5. Установка отношений между таблицами 5.6. Добавление ограничений для DataSet 5.6.1. ForeignKeyConstraint 5.6.2. UniqueConstraint 5.7. Работа с событиями DataSet 5.8. Использование Typed DataSet 5. Использование DataSet Чтобы появилась возможность использования DataSet, Вы должны включить System.Data: using System.Data Есть два основные способа использования объекта DataSet: в
рамках существующей системы управления базой данных (database
management system) или создание нового DataSet программным
путём. В типовом решении, данные запрашиваются приложением клиента
посредством URL. Когда запрос достигает соответствующего
компонента промежуточного слоя, DataSet будет создан с помощью
специального адаптера. После этого, DataSet конвертируется в
XML документ для транспортировки назад к инициатору
запроса. Потенциальная потеря точности для десятичного типа
данных (Decimal) 5.1. Использование DataSet с существующими данными Рассмотрим общепринятые способы использования DataSet с
существующими данными: [VB] [C#] 4. Проверьте ошибки во втором DataSet, исследуя его
свойство HasErrors, посредством которого можно узнать, имеет
ли ошибки какая-либо из таблиц в наборе. [VB] [C#] 9. Вызовите метод Update для SQLDataSetCommand (или ADODataSetCommand), используя объединенный DataSet как параметр. [VB] [C#] 10. Вызовите метод AcceptChanges для DataSet, что бы принять изменения, или альтернативный метод RejectChanges, чтобы отменить изменения. ds.AcceptChanges 5.2. Создание DataSet программным путём DataSet обеспечивается двумя основными конструкциями: public
DataSet() Первая конструкция для пустого DataSet, вторая создаёт
DataSet с указанным именем. [VB] [C#]
5.3. Добавление DataTable в DataSet ADO.NET дает Вам возможность вначале создать внешние
таблицы, а затем добавлять их к существующему набору данных
DataSet. (чтобы создать DataTable, см. .Net Framework SDK
Создание DataTable) [VB] [C#]
5.4. Добавление отношений между двумя
таблицами Поскольку DataSet может содержать множество объектов
DataTable, также должен быть способ связать все таблицы друг с
другом. Это может быть необходимо для организации навигации по
таблицам, и для возвращения связанных
значений. [VB] [C#]
5.5. Установка отношений между таблицами В начале, функция DataRelation должна обеспечить навигацию
от одной таблицы к другой в пределах DataSet. Это позволит
привязать все связанные объекты DataRow одной таблицы, по
заданной, единственной DataRow из связанной с ней таблицы.
Например, если дана DataRow таблицы Customers, Вы можете
получить все orders относящиеся к клиенту из таблицы
Orders. [VB] [C#]
5.6. Добавление ограничений для DataSet В реляционной базе данных должна обеспечиваться целостность данных. Один из путей поддержания такой целостности в ADO.NET, это добавление ограничений к таблицам. Ограничение, это автоматически исполняемое правило, которое определяет порядок действий, когда содержание строки так или иначе изменено. Есть два вида ограничений, доступных в ADO.NET: ForeignKeyConstraint и UniqueConstraint. 5.6.1. ForeignKeyConstraint Когда значение в строке удалено или обновлено, и это значение также используется в одной или более связанных таблиц, ForeignKeyConstraint определяет то, что случается во второй таблице, которая связана с той же самой колонкой через DataRelation. Возможные действия включают:
Используя ForeignKeyConstraint сначала создают ограничение, а затем устанавливают свойства DeleteRule и UpdateRule к одному из соответствующих значений, как показано в примере ниже: [VB] [C#] 5.6.2. UniqueConstraint Когда обязательно, чтобы все значения в столбце были уникальны, Вы можете добавить к DataTable UniqueConstraint. UniqueConstraint может быть назначен или для отдельного столбца, или на массив столбцов того же самого объекта DataTable. [VB] [C#]
5.7. Работа с событиями DataSet DataSet обеспечивает ряд событий, которые могут быть
использованы в коде пользователя. Этот события включают: [VB] [C#]
5.8. Использование Typed DataSet ADO обеспечивает отложенно-связанный доступ (late bound
access) к значениям в пределах его рекордсета через слабо
типизированные переменные. ADO.NET обеспечивает способность
обратиться к данным, содержащимся в DataSet через метафору
"Strongly-Typed". Это означает, что Вы можете обращаться к
таблицам и столбцам, которые являются частью DataSet через
простые имена и strongly typed переменные. AdoRecordSet.Find("Customerid =
'ALFKI'") Для typed DataSet в ADO.NET, тот же самый результат был бы получен с помощью следующего кода: CustomerDataSet.Customers("ALFKI").CustomerName = "Bob" Кроме удобочитаемости кода, typed DataSet позволяет
транслятору автоматически завершать строки, которые Вы
пишете. xsd.exe /d /l:C# {XSDSchemaFileName.xsd} Где: Представленный ниже пример использует typed DataSet с именем customerDataSet, чтобы загрузить список customers (заказчиков) из базы данных Northwind. Как только данные загружены, используя метод FillDataSet, организуется цикл по каждому заказчику в таблице customers, используя объект typed customerRow. Здесь, Вы имеете прямой доступ к полю customerid, в противоположность доступу к этому полю через совокупность полей (fields collection). [C#] [VB] | |||||||||||||
6.
Использование DataTable
6.1. Создание DataTable 6.2. Добавление столбцов в DataTable 6.3. Создание Expression Columns 6.4. Создание AutoIncrement столбцов 6.5. Создание первичного ключа для таблицы 6.6. Порядок применения Insert, Update и Delete 6. Использование DataTable Чтобы использовать DataTable, Вы должны подключить System.Data. 6.1. Создание DataTable Объект DataTable имеет две конструкции: public
DataTable() Следующий пример создает экземпляр объекта DataTable: [VB] [C#] В этом примере создаётся объект DataTable и устанавливается его имя. Также Вы можете создавать объект DataTable без того, чтобы сразу задавать его имя, а имя присвоить позже, воспользовавшись свойством TableName объекта DataTable: DataTable worktable =
new DataTable(); Объект DataTable создаётся с заданными по умолчанию параметрами свойств. Среди прочих свойств DataTable, свойство CaseSensitive указывает, является ли схема, которая добавляет строки к таблице зависимой от регистра. Вы можете изменять установку CaseSensitive для сравнений строки при сортировке, поиске и фильтрации (sorting, searching и filtering). Свойство MinimumCapacity определяет число строк, которое система должна создать перед получением данных. Если для вашей системы критична эффективность, Вы можете изменить установленное по умолчанию начальное значение параметра, в целях оптимизации эффективности. 6.2. Добавление столбцов в DataTable DataTable содержит совокупность объектов DataColumn. Эта совокупность определяет структуру таблицы. Чтобы добавить новый столбец в эту совокупность, используйте метод Add. Представленный ниже пример добавляет три столбца к DataTable, используя метод Add из ColumnsCollection. Метод определяет свойства DataType и ColumnName. [VB] [C#] В этом примере, сначала объявляется переменная типа DataColumn с именем "workColumn". Для C#, переменная инициализируется null. DataColumn workColumn = null; Затем, объявляется экземпляр таблицы, чтобы добавить новые столбцы, и называем её Customers. DataTable worktable = new DataTable("Customers"); После создания таблицы, начните добавлять в неё новые столбцы. Типы данных, назначаемые столбцам должны быть типами данных, принятыми в .NET FRAMEWORK, а не у OLE DB или, как определенные в базе данных типы. Чтобы установить тип, используйте System функцию GetType, которая возвращает название для требующегося типа данных. В этом примере добавляется три столбца: CustID (type: Int32), CustomerNameLast (type: String), и CustomerNameFirst (type: String). workColumn =
workTable.Columns.Add("CustID", Метод GetType возвращает null, если указанный тип не может
быть загружен. Public DataColumn
Add(String columnname, Type type) 6.3. Создание Expression Columns ADO.NET позволяет также создавать и определять Expression (выражение) столбцы, которые содержат вычисляемые значения. Выражения в ADO.NET используются для: - Фильтрации; Чтобы создавать Expression столбец, установите свойство DataType на тип, соответствующий возвращаемому выражением значения. После этого, установите свойство Expression на допустимое выражение. Следующий пример показывает, как создать Expression столбец, который вычисляет налог с продаж 8.6 процентов (.086): [VB] [C#] Вы также можете создать Expression столбец, используя метода Add. Например, показанный ниже код добавляет столбец, который вычисляет для заказчика скидку в 10 процентов от закупки. Выражение умножает столбец "Purchases" на 10 процентов [VB] [C#] Выражения DataSet могут ссылаться на другие Expression столбцы. Однако, циклическая зависимость, в которой два выражения ссылаются друг на друга, вызовет ошибку. Для выяснения правил использования выражений, см. соответствующую тему справочника по .NET Framework SDK, для свойств Expression класса DataColumn. 6.4. Создание AutoIncrement столбцов Другая особенность DataColumn, это возможность
автоприращения (auto-incrementation). Auto-incrementing
столбец автоматически увеличивает значение, содержащееся в
столбце, когда добавляются новые строки. Чтобы создавать
Auto-incrementing столбец, установите свойство AutoIncrement
этого столбца к истине. После этого, отсчёт значений столбца
начнётся со значения, определенного в свойстве столбца
AutoIncrementSeed. При добавлении каждой строки, значение
столбца AutoIncrement будет увеличиваться на величину,
указанную в свойстве столбца AutoIncrementStep. [VB] [C#] По аналогии, можно заставить столбец быть read-only (только для чтения), установив его свойство ReadOnly в истину. 6.5. Создание первичного ключа для таблицы Общее принятым правилом для базы данных является то, что
каждая таблица имеет столбец, или группу столбцов, которые
уникально идентифицирует каждую строку в таблице. Этот столбец
(или столбцы) называется первичным ключом (primary
key). workColumn.AllowNull = false; Свойство Unique определяет, должны ли значения в столбце быть уникальными. Другими словами, никакие два значения в столбце не могут быть идентичны. Так как столбец будет первичным ключом, устанавливать это значение в true. workColumn.Unique = true; Теперь, когда столбец имеет всё необходимое для выполнения роли первичного ключа, ему может быть установлено свойство PrimaryKey объекта DataTable: [VB] [C#] Если необходимо определить дополнительные столбцы, как часть первичного ключа, это будет выглядеть следующим образом: [VB] [C#] 6.6. Порядок применения Insert, Update и Delete
Вообще, все Insert, Update и Delete передаются к SQL Server в том же самом порядке строки, в каком он был возвращён первоначальной инструкцией Update. Порядок, в котором исполняются запланированные инструкцией Update изменения, при некоторых обстоятельствах, может вызвать проблемы при модификации. Например, рассмотрим следующий алгоритм: - Заполним объект DataSet, включая ключевой столбец. Вышеупомянутая последовательность операций приведёт к ошибке. Это произойдёт потому, что новая строка вставлена в набор данных в порядке сортировки. Все Insert, Update и Delete обрабатываются последовательно, так что вставка новой строки произойдёт раньше, чем будет выполнена модификация старой строки. | |
7.
Работа с данными в таблицах ADO.NET
7.1. Добавление данных в таблицу 7.2. Состояния строки 7.3. Removing или Deleting DataRow из таблицы 7.4. Работа с данными в таблице 7.5. Добавление и чтение информации об ошибках строки 7.6. Принятие или отклонение изменений строк 7.7. Работа с событиями DataTable 7.8. Фильтрация и сортировка строк в таблице 7.9. Optimistic Concurrency 7.10. Исполнение транзакций 7. Работа с данными в таблицах ADO.NET 7.1. Добавление данных в таблицу После того, когда создана таблица со столбцами и ключами, можно добавлять данные. Представленный ниже код добавляет десять строк в таблицу Customers. [VB] [C#] В этом коде объявляется новая переменная с типом DataRow. Новый объект DataRow возвращается при вызове метода NewRow. DataTable создаёт объект DataRow, основанный на структуре таблицы (как это определено в ColumnsCollection). [VB] [C#] После этого, Вы можете работать с недавно созданными
строками через индекс или через имя столбца. Обе из ниже
следующих строк кода допустимы: [VB] [C#] После того, как строка заполнена значениями, её можно добавить в RowsCollection таблицы, используя метод Add. [VB] [C#] В дополнение к добавлению строк этим путём, мы можем также добавлять новую строку, получая значения из массива (типизированного, как объект) и используя метод Add. [VB] [C#] Этот способ просто создаёт новую строку внутри таблицы и устанавливает для значения столбца, значение из объекта массив. Обратите внимание, что последовательность значений в массиве согласована с последовательностью значений столбца в таблице. 7.2. Состояния строки Каждая DataRow имеет свойство RowState, которое определяет
её состояние.
7.3. Removing или Deleting DataRow из таблицы При выполнении операций удаления одной или более строк из
таблицы, обратите внимание на то, что removing не то же, что
deleting. Важность этого различия будет рассмотрена позже в
обсуждении способов сохранения значений таблицы в источнике
данных. [VB] [C#] ИЛИ [VB] [C#] После вызова этого метода, указанная строка будет удалена из совокупности строк. В отличии от этого, Вы можете вызвать метод Delete для DataRow, чтобы изменить её состояние на Deleted: [VB] [C#] Отметка строки, как удаленной, говорит о том, что когда
будет вызван метод AcceptChanges объекта DataTable, строка
будет удален из таблицы. Это приведёт к изменению RowState для
Deleted строки. Напротив, если вызван RejectChanges, RowState
этой строки возвратится к тому состоянию, которое до этого
соответствовало состоянию удалено (Deleted). 7.4. Работа с данными в таблице Теперь, когда создана таблица содержащая столбцы, первичный ключ и данные, можете заняться отображением её содержания. В этом примере, DataSet фильтруется так, чтобы Вы работали только с текущей версией строки. [VB] [C#] Метод Select класса DataTable дает Вам возможность отыскать
набор строк, соответствующий указанным критериям. Метод
возвращает массив объектов DataRow. [VB] [C#] Это означает, что в течение состояния строки Proposed, Вы можете применять логику проверки правильности значений отдельных столбцов, анализируя результаты события ColumnChange объекта DataTable. Таблица передаёт ссылку на изменяемый столбец и состояние Proposed в событии ColumnChange. Пользователь может изменять состояние Proposed или генерировать исключение, для отмены редактирования. Строка выводится из состояния Proposed, когда вызывается EndEdit. Вы можете также отменять любое изменение при редактировании, в тот момент, когда строка находится в состоянии Proposed, с помощью вызова CancelEdit. 7.5. Добавление и чтение информации об ошибках строки Поскольку конечные пользователи редактируют значения в таблице, они могут допускать при этом ошибки. В этих случаях, Вы не можете прервать действия пользователя, когда он находятся в процессе редактирования данных, а просто выводите информацию об ошибке в строке на его дисплей, когда редактирование завершено. Объект DataRow поддерживает эту возможность через свойство RowError для каждой строки. Представленные ниже два примера показывают как выводить/читать (Add/Read) информацию об ошибке, связанной с объектом DataRow.Пример 1: [VB] [C#] Пример 2: [VB] [C#] Первый пример берет номер строки (Row) и добавляет сообщение об ошибках (ErrorString). Второй пример печатает RowError для каждой строки workTable, используя ассоциируемый с ошибками текст. 7.6. Принятие или отклонение изменений строк Если Вы уверены относительно внесённых изменений,
необходимо принять эти изменения и передать текущие значения
строки, чтобы быть установить состояние Current. (Обратите
внимание, что всё это относится к данным, находящимся DataSet,
который размещён в памяти). Принятие или отклонение изменений
в DataSet вызовет обновление данных в источнике (для получения
дополнительной информации, прочтите ADO.NET Managed
Providers). Пример 1: [VB] [C#] Пример 2: [VB] [C#] Первый пример принимает все изменения, которые были сделаны к таблице. Второй пример вносит изменения в цикле и принимает каждое с помощью приёма Row-by-Row. Для исполнения AcceptChanges, код примера исследует свойство HasErrors. [VB] [C#] DataRow позволяет Вам вводить строку ошибки и ассоциировать
её со строкой в таблице. Если любой строке в таблице
ассоциировали строку ошибки для этой строки, свойство
HasErrors возвратит true. Во втором примере выполняется
исследование строк, и изменения принимаются для тех, которые
не имеют ошибок. 7.7. Работа с событиями DataTable Объект DataTable обеспечивает ряд событий, которые могут быть обработаны кодом пользователя. Эти события включают: - ColumnChange В представленном ниже примере, создаются три метода: MyColChanging, MyRowChanging и MyRowChanged. Каждый из этих методов вызывается, когда столбец или строка будет изменена. [VB] [C#]
7.8. Фильтрация и сортировка строк в таблице Метод Select дает возможность пользователям отбирать строки
по трём критериям: выражению фильтра, порядку сортировки и
DataViewRowState. [VB] [C#] Вы можете запросить все строки с фамилией Smith, упорядоченные по столбцу CustomerNameFirst. [VB] [C#] В многопользовательской среде, есть два основных способа
обновления данных в СУБД: Optimistic и Pessimistic Concurrency
(параллелизм). Например: 13:00. User1 читает строку в базе данных со следующими значениями: CustID
LastName
FirstName
13:01. User2 читает ту же самую строку
Так как во время модификации значения в базе данных соответствуют оригиналу, модификация для user2 проходит успешно. 13:05. User1 изменяет имя Bob на James и пробует обновить строку.
Так как первоначальное значение для user1 было Bob, а
значение в базе данных из-за модификации user2 стало Robert,
попытка модификации имени для user1 окончится сбоем. Update Table1 set x = newx1, y = newy where datetimestamp = originaldatetime ИЛИ Update Table1 set x = newx1, y = newy where rowversion = originalrowversion Чтобы сохранять date-time stamp или точную версию строки,
используйте триггер для таблицы, чтобы значения
модифицировались при любых изменениях в строке. CREATE PROCEDURE
AuthorUpdate Второй набор параметров содержит первоначальные значения
полей, которые были загружены из источника данных. Это
позволяет выполнить сравнение в предложении WHERE,
используемом в инструкции модификации. Au_id = "999-99-9999" Предположим, что в результате выполненной Вами модификации
изменится телефонный номер на 222 111-1111. Однако, ели до
вашей модификации, но после того, как Вы считали данные,
другой пользователь изменит фамилию Jane со Smith на Doe, при
попытке выполнения Вами модификации, она не сможет быть
выполнена, потому что столбец Au_Lname больше не соответствует
первоначальному значению. 7.10. Исполнение транзакций Транзакции используются, чтобы управлять блокировками в
базах данных. Например, в стандартных бухгалтерских проводках,
необходимо дебетовать один счёт и в то же самое время
кредитовать другой. Из-за возможных ошибок компьютера,
вызванных сбоем в его работе (отключение электропитания,
потеря сети и т.д.), есть вероятность того, что одна запись
изменена/добавлена, а другая нет. Транзакции дают возможность
избежать таких ситуаций. Так же, как в ADO, транзакции в
ADO.NET обрабатываются на уровне базы данных: т.е. ваша база
данных должна поддержать транзакции. begin transaction
В ADO.NET (как и в ADO) Вы можете управлять транзакциями
через объект Connection. Фактически, когда Вы используете
ADOConnection, используется та же самая основная модель
транзакций OLEDB. Поэтому, если Вы могли определять транзакции
для вашей базы данных используя ADO, Вы также можете
определять их и средствами ADO.NET. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
8. Свод событий ADO.NET Следующие таблицы содержат события, генерируемые компонентами ADONET. DataSetCommand Events
Connection Events
Command Events
|
|