Каждая измененная запись обновляется отдельно, а не как часть транзакции или пакетной операции. Причем порядок обновления записей определяется порядком их расположения в объекте DataTable.
Для явного управления порядком выполнения операций для заданной таблицы можно использовать методы GetChanges или Select, которые доступны на уровне либо объекта DataSet, либо объекта DataTable. Эти методы используются для извлечения отдельных наборов записей с разными состояниями записей.
Допустим, необходимо обновить базу данных Novelty данными из объекта dsEmployees с помощью объекта daDepartments. Причем сначала требуется выполнить все вставки, затем все обновления, а потом все удаления. Это можно сделать, трижды вызывая метод GetChanges с указанием соответствующих разных состояний записей. После каждого вызова метода GetChanges вызывается метод Update объекта DataAdapter с передачей объекта DataTable, возвращенного методом GetChanges.
dt = dsEmployeeInfo.Tables("Departments")
Внести изменения для каждого типа состояния.
dtChanged = dt.GetChanges(DataRowState.Added)
daDepartments.Update(dtChanged)
dtChanged = dt.GetChanges(DataRowState.Modified)
daDepartments.Update(dtChanged)
dtChanged = dt.GetChanges(DataRowState.Deleted)
daDepartments.Update(dtChanged)
Этот код можно записать более компактно.
dt = dsEmployeeInfo.Tables("Departments")
' Внести изменения для каждого типа состояния.
daDepartments.Update(dt.GetChanges(DataRowState.Added))
daDepartments.Update(dt.GetChanges(DataRowState.Modifled))
daDepartments.Update(dt.GetChanges(DataRowState.Deleted))
Аналогичный результат можно получить с помощью метода Select.
dt = dsEmployeeInfo.Tables("Departments")
' Внести изменения для каждого типа состояния.
daDepartments(Nothing, Nothing, _
dt.GetChanges(DataViewRowState.Added))
daDepartments.Update(Nothing, Nothing, _
dt.GetChanges(DataViewRowState.ModifiedCurrent))
daDepartments.Update(Nothing, Nothing, _
dt.GetChanges(DataViewRowState.Deleted))
Преимущество использования метода Select вместо GetChanges заключается в том, что он может выполнять фильтрацию и сортировку.
Здесь следует напомнить о разнице между операциями удаления записи с помощью методов Remove и о которой сообщалось в главе 5, "ADO.NET: объект DataSet". При использовании метода Remove запись навсегда удаляется из коллекции, а при удалении с помощью метода Delete — только отмечается как удаленная. При обновлении источника данных данными из объекта DataTable с помощью объекта DataAdapter нужно использовать метод Delete, а не Remove. Когда объект DataAdapter встречает помеченную для удаления запись, он автоматически выполняет команду DeleteCommand для базы данных, чтобы осуществить синхронизацию с объектом DataTable. Если вместо метода Delete использовать Remove, то объект DataAdapter не обнаружит уже удаленную запись из объекта DataTable и не сможет удалить ее из источника данных.
Указание команд обновления
Объект DataAdapter не создает автоматически команды INSERT, UPDATE и DELETE для обновления источника данных в соответствии с изменениями данных в объекте DataSet. Если при вызове команды метода Update не была указана команда INSERT, UPDATE или DELETE, то генерируется исключительная ситуация. Эти команды можно указать одним их следующих способов:
• использовать объект CommandBuilder для автоматической генерации команд во время выполнения приложения;
• явно запрограммировать эти команды;
• использовать компонент DataAdapter DesignTime Component и мастер конфигурирования объекта DataAdapter Configuration Wizard.
Использование объекта CommandBuilder
Это самый простой способ, но он связан с существенными ограничениями. Он аналогичен применению метода BatchUpdate в модели ADO 2.X. Когда объект CommandBuilder связывается с соответствующим ему объектом DataAdapter, он автоматически может задавать значения свойств InsertCommand, UpdateCommand и DeleteCommand для данного объекта DataAdapter. А если эти свойства имеют ненулевые значения (т.е. для них не задано значение Nothing), то объект-команда уже существует и объект CommandBuilder не переопределяет ее.
НА ЗАМЕТКУ
Как и следовало ожидать, для каждого типа провайдера данных .NET используется специализированный объект: SqlDataAdapter, OledbDataAdapter или OdbcDataAdapter.
Для автоматической генерации команд нужно указать объект SelectCommand адаптера данных DataAdapter. Объект CommandBuilder использует схему таблицы, полученную с помощью метода Select объекта SelectCommand для генерации соответствующей команды вставки, обновления или удаления. Учтите, что поля, возвращаемые объектом SelectCommand, должны содержать первичный ключ или поле с уникальными значениями.
Изменение текста команды SELECT после автоматической генерации команд обновления может привести к возникновению исключительных ситуаций при одновременном выполнении этой команды обновления. Если в исходной команде SELECT, на основании которой автоматически генерируются команды обновления данных, содержались поля, которых уже нет в генерированной команде, то при выполнении одной из команд обновления с помощью метода Update объекта DataAdapter может произойти попытка обращения к уже несуществующим полям и возникновение исключительной ситуации. Для исключения этой проблемы следует вызвать метод RefreshSchema объекта CommandBuilder после изменения свойства SelectCommand объекта DataAdapter или после изменения текста (объект CommandText) данной команды.
Читать дальше