Класс DbCommandBuilder

Класс DbCommandBuilder предназначен для автоматического генерирования однотабличных SQL-команд, которые позволяют согласовывать изменения, вносимые в объект DataSet, со связанной с ним БД. Например, если создать экземпляр DbCommandBuilder и связать его с объектом DbDataAdapter, то DbCommandBuilder сгенерирует SQL-запросы на обновление таблицы на основе запроса, указанного в свойстве SelectCommand объекта DbDataAdapter.

Для генерации запросов UPDATE, INSERT и DELETE методы класса DbCommandBuilder обращаются к БД за именами базовой таблицы и столбцов, а также о первичных ключах в таблице и в выборке данных из этой таблицы.

SQL-запросы на обновление данных генерируются при выполнении следующих условий:

  • запрос возвращает данные только из одной таблицы (обновляемого представления);

  • в таблице определен первичный ключ;

  • столбец с первичным ключом таблицы входит в выборку данных из этой таблицы.

Первичный ключ гарантирует, что DbCommandBuilder обновит не более одной записи.

Если свойство SelectCommand задается динамически во время выполнения клиентского приложения, например, при помощи интерактивного запроса, принимающего от пользователя клиентского приложения текстовые команды, то во время работы приложения нельзя задавать соответствующие свойства InsertCommand, UpdateCommand или DeleteCommand. Если объект DataTable сопоставляется с одной таблицей БД или создается из нее, то можно воспользоваться преимуществом объекта DbCommandBuilder для автоматического создания запросов DeleteCommand, InsertCommand и UpdateCommand объекта DbDataAdapter.

Минимальным требованием для работы автоматического создания команд является задание свойства SelectCommand. Схема таблицы, получаемая свойством SelectCommand, определяет синтаксис автоматически созданных инструкций INSERT, UPDATE и DELETE.

Для получения метаданных, необходимых для создания команд INSERT, UPDATE и DELETE, объект DbCommandBuilder должен выполнить команду SelectCommand, что приводит к дополнительному взаимодействию с источником данных, а это может снизить производительность клиентского приложения. Если такое положение дел нежелательно, то вместо использования DbCommandBuilder следует задавать команды манипулирования данными явным образом.

Свойство SelectCommand должно также возвратить, по крайней мере, один столбец первичного ключа или столбец с атрибутом UNIQUE. Если отсутствует и то и другое, то возникнет исключение InvalidOperation и автоматическая генерация команд выполняться не будет.

При наличии связи с DataAdapter объект DbCommandBuilder автоматически создает свойства InsertCommand, UpdateCommand и DeleteCommand объекта DataAdapter, если они являются пустыми ссылками. Если для свойства уже существует значение Command, то оно и используется.

Представления БД, созданные соединением двух или более таблиц, не считаются одной таблицей БД. В данном случае нельзя использовать класс DbCommandBuilder для автоматического создания команд. Необходимо указывать команды явным образом.

Действия, выполняемые автоматически сконструированными командами, приведены в таблице 31.

Таблица 31. Правила конструирования команд
Команда Действия
InsertCommand
  1. Выполняет операцию вставки строки в источнике данных для всех строк таблицы со свойством RowState, равным Added

  2. Вставляет значения для всех обновляемых столбцов (за исключением идентификаторов, выражений или временных меток)

UpdateCommand
  1. Выполняет обновление строк в источнике данных для всех строк таблицы со свойством RowState, равным Modified

  2. Обновляет значения всех столбцов, за исключением столбцов, которые не являются обновляемыми, например, идентификаторов или выражений

  3. Обновляет все строки, в которых значения столбцов в источнике данных совпадают со значениями столбцов первичных ключей строки и в которых оставшиеся в источнике данных столбцы совпадают с исходными значениями строки

Примечание

Дополнительные сведения см. ниже в описании модели оптимистичного параллелизма для обновлений и удалений

DeleteCommand
  1. Выполняет операцию удаления строки в источнике данных для всех строк таблицы, у которых свойство RowState равно Deleted

  2. Удаляет все строки, в которых значения столбцов совпадают со значениями столбцов первичных ключей строки и в которых оставшиеся в источнике данных столбцы совпадают с исходными значениями строки

Примечание

Дополнительные сведения см. ниже в описании модели оптимистичного параллелизма для обновлений и удалений


Логика автоматического создания команд для операций UPDATE и DELETE базируется на модели оптимистичного параллелизма, т. е. записи не блокируются для редактирования и могут быть в любое время изменены другими пользователями или процессами. Вследствие того, что запись можно изменить после ее возврата из инструкции SELECT, но до выполнения операции UPDATE или DELETE, то автоматически созданная инструкция UPDATE или DELETE содержит предложение WHERE, указывающее на то, что строка обновляется только в случае наличия в ней всех исходных значений и она не была удалена из источника данных. Это делается во избежание перезаписи новых данных. Когда автоматически созданное обновление пытается обновить строку, которая была удалена или не содержит исходные значения, найденные в DataSet, команда не изменяет записи и вызывается исключение DBConcurrencyException.

Если требуется выполнить операцию UPDATE или DELETE независимо от исходных значений, необходимо явно задать свойство UpdateCommand для DataAdapter и не полагаться на автоматическое создание команд.

На автоматическое создание команд накладываются следующие ограничения:

  • в конструируемой команде могут использоваться только несвязанные таблицы. Логика автоматического создания команд для операций INSERT, UPDATE или DELETE предполагает использование изолированных таблиц, не принимая во внимание связи с другими таблицами в источнике данных. В результате при вызове UPDATE для выполнения изменений столбца, участвующего в ограничении внешнего ключа БД, может произойти ошибка. Чтобы избежать её, не следует использовать DbCommandBuilder для обновления столбцов, вовлеченных в ограничение внешнего ключа (или в другие ограничения целостности). Вместо этого нужно явно задавать команды, используемые для выполнения операции.

  • имена таблиц и столбцов не должны содержать спецсимволов. Логика автоматического создания команд не допускает в именах столбцов или таблиц любых специальных символов, например, пробелов, точек, двойных кавычек или других символов, отличных от алфавитно-цифровых, однако СУБД ЛИНТЕР разрешает спецсимволы внутри двойных кавычек. Поддерживаются указанные полностью имена таблиц в виде catalog.schema.table.

Чтобы автоматически создать команды объекта DataAdapter, необходимо:

  1. установить его свойство SelectCommand;

  2. создать объект CommandBuilder, указав в аргументе тот объект DataAdapter, для которого должна автоматически создаваться команда.

При изменении свойства CommandText, принадлежащего свойству SelectCommand, после автоматического создания команд INSERT, UPDATE или DELETE может возникнуть исключение. Например, если измененное свойство SelectCommand.CommandText содержит сведения о схеме, которые не согласованы с используемыми SelectCommand.CommandText сведениями при автоматическом создании команд INSERT, UPDATE или DELETE, то последующие вызовы к методу DataAdapter.Update могут содержать попытки обращения к столбцам, которых больше нет в текущей таблице, на которую ссылается SelectCommand, и в этом случае возникнет исключение.

Для обновления сведений о схеме, используемой CommandBuilder для автоматического создания команд, следует вызвать метод RefreshSchema объекта CommandBuilder.

Чтобы узнать, какая команда была автоматически создана, необходимо с помощью методов GetInsertCommand, GetUpdateCommand и GetDeleteCommand объекта CommandBuilder получить ссылку на автоматически созданные команды и проверить свойство CommandText, соответствующее команде.

Следующий пример выводит на консоль автоматически созданную команду UPDATE:

Console.WriteLine(builder.GetUpdateCommand().CommandText)

В следующем примере повторно создается таблица AUTO из набора данных autoDS. Метод RefreshSchema вызывается для внесения новых сведений о столбцах в автоматически созданные команды.

// C#
    …
    adapter.SelectCommand.CommandText =
      "select MAKE, MODEL from SYSTEM.AUTO";
    builder.RefreshSchema();

    autoDS.Tables.Remove(autoDS.Tables["AUTO"]);
    adapter.Fill(autoDS, "AUTO");

Конструкторы класса LinterDbCommandBuilder приведены в таблице 32.

Таблица 32. Конструкторы класса LinterDbCommandBuilder
Конструктор Описание
LinterDbCommandBuilder Создает новый экземпляр класса LinterDbCommandBuilder.
LinterDbCommandBuilder(LinterDbDataAdapter) Создает новый экземпляр класса LinterDbCommandBuilder со связанным с ним объектом LinterDbDataAdapter.

Свойства класса LinterDbCommandBuilder приведены в таблице 33.

Таблица 33. Свойства класса LinterDbCommandBuilder
Свойство Описание
CatalogLocation Предоставляет/устанавливает объект CatalogLocation для экземпляра класса DbCommandBuilder.
CatalogSeparator

Предоставляет/устанавливает символ, который используется в качестве разделителя между идентификатором каталога и остальными идентификаторами.

Примечание

В текущей версии ADO.NET-провайдера СУБД ЛИНТЕР данное свойство не поддерживается.

ConflictOption Предоставляет/устанавливает значение типа ConflictOption, которое используется объектом DbCommandBuilder.
DataAdapter Предоставляет/устанавливает объект DbDataAdapter, который связан с объектом DbCommandBuilder.
QuotePrefix Предоставляет/устанавливает начальный символ или символы, используемые для именования объектов БД, имена которых содержат русские буквы или специальные символы.
QuoteSuffix Предоставляет/устанавливает конечный символ или символы, используемые для именования объектов БД, имена которых содержат русские буквы или специальные символы.
SchemaSeparator Предоставляет или задает строку, которую можно использовать в качестве разделителя имени владельца таблицы и имени таблицы в полной спецификации таблицы.
SetAllValues Предоставляет/устанавливает признак, какие значения столбца включены в сгенерированном операторе UPDATE: все или только измененные.

Методы класса LinterDbCommandBuilder приведены в таблице 34.

Таблица 34. Методы класса LinterDbCommandBuilder
Метод Описание
DeriveParameters Извлекает сведения о параметрах из хранимой процедуры, указанной в объекте LinterDbCommand, и включает их в коллекцию параметров Parameters указанного объекта LinterDbCommand.
GetDeleteCommand Предоставляет автоматически сгенерированный для выполнения операций удаления в БД объект DbCommand.
GetDeleteCommand(Boolean) Предоставляет автоматически сгенерированный для выполнения операций удаления в БД объект DbCommand с заданным правилом именования параметров.
GetInsertCommand Предоставляет автоматически сгенерированный для выполнения операций добавления записей в БД объект DbCommand.
GetInsertCommand(Boolean) Предоставляет автоматически сгенерированный для выполнения операций добавления записей в таблицу БД объект DbCommand с заданным правилом именования параметров.
GetUpdateCommand Предоставляет автоматически сгенерированный для выполнения операции обновления записей в БД объект DbCommand.
GetUpdateCommand(Boolean) Предоставляет автоматически сгенерированный для выполнения операции обновления записи в таблице БД объект DbCommand с заданным правилом именования параметров.
QuoteIdentifier Предоставляет обрамленный прямыми двойными кавычками указанный идентификатор в спецификации объекта БД.
RefreshSchema Обновляет автоматически сгенерированные SQL-операторы, связанные с указанным объектом DbCommandBuilder.
UnquoteIdentifier Предоставляет указанный идентификатор в спецификации объектов БД без обрамляющих его кавычек.