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


Создание команд с помощью CommandBuilders

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

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

Элемент DbCommandBuilder должен выполнить SelectCommand, чтобы вернуть метаданные, необходимые для создания команд INSERT, UPDATE и DELETE SQL. В результате необходимо дополнительное путешествие к источнику данных, и это может препятствовать производительности. Чтобы добиться оптимальной производительности, укажите команды явно, а не с помощью DbCommandBuilder.

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

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

Представления базы данных, созданные путем объединения двух или более таблиц, не считаются одной таблицей базы данных. В данном случае нельзя использовать DbCommandBuilder для автоматической генерации команд; необходимо явно указать команды. Сведения о явной установке команд для разрешения обновлений обратно в источник данных см. в разделе DataSet.

Возможно, вам потребуется связать выходные параметры с обновленной строкой DataSet. Одна из распространенных задач — получение значения автоматически созданного поля удостоверения или метки времени из источника данных. По умолчанию выходные DbCommandBuilder параметры не сопоставляются со столбцами в обновляемой строке. В этом случае необходимо однозначно указать команду. Пример сопоставления автоматически сгенерированного поля идентификатора со столбцом вставленной строки см. в разделе "Получение значений идентификаторов или автонумеров".

Правила для автоматически созданных команд

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

командование Правило
InsertCommand Вставляет строку непосредственно в источник данных для всех строк в таблице, имеющих значение RowState равное Added. Вставляет значения для всех столбцов, которые можно изменять (но не для столбцов, таких как идентификаторы, выражения или временные метки).
UpdateCommand Обновляет строки в источнике данных для всех строк в таблице с RowState по Modified. Обновляет значения всех столбцов, кроме тех, которые нельзя обновить, например идентификаторы или выражения. Обновляет все строки, в которых значения столбцов в источнике данных соответствуют значениям столбца первичного ключа строки, а остальные столбцы в источнике данных соответствуют исходным значениям строки. Дополнительные сведения см. в разделе "Модель оптимистического параллелизма для обновлений и удалений", далее в этом разделе.
DeleteCommand Удаляет строки в источнике данных для всех строк в таблице со значением RowStateDeleted. Удаляет все строки, в которых значения столбцов соответствуют значениям столбца первичного ключа строки, а остальные столбцы в источнике данных соответствуют исходным значениям строки. Дополнительные сведения см. в разделе "Модель оптимистического параллелизма для обновлений и удалений", далее в этом разделе.

Оптимистическая модель параллелизма для обновлений и удалений

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

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

Ограничения логики автоматического создания команд

Ограничения, которые применяются к автоматической генерации команд, следующие.

Только несвязанные таблицы

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

Имена таблиц и столбцов

Логика автоматического создания команд может завершиться ошибкой, если имена столбцов или имена таблиц содержат специальные символы, такие как пробелы, точки, кавычки или другие нефазные символы, даже если они разделены скобками. В зависимости от поставщика настройка параметров QuotePrefix и QuoteSuffix может позволить логике генерации обрабатывать пробелы, но она не может экранировать специальные символы. Поддерживаются полные имена таблиц в форме catalog.schema.table .

Использование CommandBuilder для автоматического создания инструкции SQL

Чтобы автоматически создать инструкции SQL для DataAdapter, сначала задайте свойство SelectCommand объекта DataAdapter, а затем создайте объект CommandBuilder и укажите в качестве аргумента DataAdapter, для которого CommandBuilder автоматически создаст инструкции SQL.

' Assumes that connection is a valid SqlConnection object
' inside of a Using block.  
Dim adapter As SqlDataAdapter = New SqlDataAdapter( _  
  "SELECT * FROM dbo.Customers", connection)  
Dim builder As SqlCommandBuilder = New SqlCommandBuilder(adapter)  
builder.QuotePrefix = "["  
builder.QuoteSuffix = "]"  
// Assumes that connection is a valid SqlConnection object  
// inside of a using block.  
SqlDataAdapter adapter = new SqlDataAdapter(  
  "SELECT * FROM dbo.Customers", connection);  
SqlCommandBuilder builder = new SqlCommandBuilder(adapter);  
builder.QuotePrefix = "[";  
builder.QuoteSuffix = "]";  

Изменение SelectCommand

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

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

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

В следующем примере кода записывается в консоль команда обновления, которая была создана автоматически.

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

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

' Assumes an open SqlConnection and SqlDataAdapter inside of a Using block.  
adapter.SelectCommand.CommandText = _  
  "SELECT CustomerID, ContactName FROM dbo.Customers"  
builder.RefreshSchema()  
  
custDS.Tables.Remove(custDS.Tables("Customers"))  
adapter.Fill(custDS, "Customers")  
// Assumes an open SqlConnection and SqlDataAdapter inside of a using block.  
adapter.SelectCommand.CommandText =
  "SELECT CustomerID, ContactName FROM dbo.Customers";  
builder.RefreshSchema();  
  
custDS.Tables.Remove(custDS.Tables["Customers"]);  
adapter.Fill(custDS, "Customers");  

См. также