Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Вы можете использовать метод Merge для объединения содержимого массива DataSet, DataTable или DataRow в существующий DataSet
. Несколько факторов и параметров влияют на то, как новые данные объединяются в существующий DataSet
.
Первичные ключи
Если таблица, получающая новые данные и схему из слияния, имеет первичный ключ, новые строки из входящих данных сопоставляются с существующими строками, имеющими те же Original значения первичного ключа, что и в входящих данных. Если столбцы из входящей схемы соответствуют существующим схемам, данные в существующих строках изменяются. Столбцы, не соответствующие существующей схеме, игнорируются или добавляются в зависимости от параметра MissingSchemaAction. Новые строки со значениями первичного ключа, которые не соответствуют существующим строкам, добавляются в существующую таблицу.
Если у входящих или существующих строк состояние Added, их значения первичных ключей сопоставляются с использованием значения первичного ключа Current строки Added
, поскольку версия Original
строки не существует.
Если входящая таблица и существующая таблица содержат столбец с одинаковым именем, но разными типами данных, создается исключение и вызывается событие MergeFailedDataSet
. Если входящая таблица и существующая таблица имеют определенные ключи, но первичные ключи предназначены для разных столбцов, создается исключение, и событие MergeFailed
инициируется в DataSet
.
Если таблица, получающая новые данные из слияния, не имеет первичного ключа, новые строки из входящих данных не могут быть сопоставлены с существующими строками в таблице и вместо этого добавляются в существующую таблицу.
Имена таблиц и пространства имен
DataTable объектам можно по желанию присваивать значение свойства Namespace. Когда назначаются значения Namespace, DataSet может содержать несколько объектов DataTable с одинаковым значением TableName. Во время операций слияния используются как TableName, так и Namespace для идентификации цели слияния. Если Namespace не назначен, используется только TableName для идентификации целевого объекта слияния.
Замечание
Это поведение изменилось в версии 2.0 платформы .NET Framework. В версии 1.1 пространства имен поддерживаются, но игнорируются во время операций слияния. По этой причине поведение DataSet, использующего значения свойств Namespace, будет отличаться в зависимости от версии .NET Framework, которая у вас установлена. Например, предположим, что у вас есть два DataSets
, которые содержат DataTables
с одинаковыми значениями свойств TableName, но разными значениями свойств Namespace. В версии 1.1 платформы .NET Framework различные Namespace имена будут игнорироваться при слиянии двух DataSet объектов. Однако, начиная с версии 2.0, слияние приводит к созданию двух новых DataTables
в целевом объекте DataSet. Исходный код DataTables
не влияет на слияние.
Сохранить изменения
При передаче массива DataSet
, DataTable
или DataRow
методу Merge
можно включить необязательные параметры, указывающие, следует ли сохранять изменения в существующем DataSet
, и как обрабатывать новые элементы схемы, найденные в входящих данных. Первый из этих параметров после входящих данных является логическим флагом, PreserveChangesкоторый указывает, следует ли сохранять изменения в существующем DataSet
. Если установлен флаг PreserveChanges
, входящие значения не перезаписывают существующие значения в версии строки true
существующей строки. Если для флага задано значение PreserveChanges
, входящие значения перезаписывают существующие значения в версии строки false
.
PreserveChanges
Если флаг не указан, он имеет false
значение по умолчанию. Дополнительные сведения о версиях строк см. в разделе "Состояния строк" и "Версии строк".
Если PreserveChanges
это true
, данные из существующей строки сохраняются в Current версии существующей строки, а данные из Original версии существующей строки перезаписываются данными из Original
версии строки входящей строки. Для RowState существующей строки задано значение Modified. Применяются следующие исключения:
Если для существующей строки установлено значение
RowState
Deleted
, этоRowState
остаетсяDeleted
и не устанавливается в значениеModified
. В этом случае данные из входящей строки будут по-прежнему храниться в версии строкиOriginal
существующей строки, перезаписывая версиюOriginal
, если только входящая строка не имеетRowState
значенияAdded
.Если входящая строка имеет значение
RowState
Added
, данные из версии строкиOriginal
существующей строки не будут перезаписаны данными из входящей строки, так как у входящей строки нет версии строкиOriginal
.
Когда PreserveChanges
равно false
, обе версии строк Current
и Original
в существующей строке перезаписываются данными из входящей строки, а RowState
существующей строки устанавливается в RowState
из входящей строки. Применяются следующие исключения:
Если в входящей строке имеется
RowState
Unchanged
, и существующая строка имеетRowState
Modified
,Deleted
илиAdded
, тоRowState
существующей строки устанавливается наModified
.Если входящая строка имеет
RowState
Added
, а существующая строка имеетRowState
Unchanged
,Modified
илиDeleted
, тоRowState
существующей строки устанавливается вModified
. Кроме того, данные из версии существующей строки не перезаписываются данными изOriginal
входящей строки, поскольку у входящей строки отсутствуетOriginal
версия строки.
MissingSchemaAction
Можно использовать необязательный MissingSchemaAction параметр Merge
метода, чтобы указать способ Merge
обработки элементов схемы в входящих данных, которые не являются частью существующего DataSet
.
В следующей таблице описаны опции для MissingSchemaAction
.
Параметр MissingSchemaAction | Описание |
---|---|
Add | Добавьте новые сведения DataSet о схеме и заполните новые столбцы входящими значениями. Это значение по умолчанию. |
AddWithKey | Добавьте новую схему и информацию о первичном ключе в DataSet , а новые столбцы заполните входящими значениями. |
Error | Выбросьте исключение, если обнаружено несоответствие сведений о схеме. |
Ignore | Игнорировать новые сведения о схеме. |
Ограничения
Merge
При использовании метода ограничения не проверяются до тех пор, пока все новые данные не будут добавлены в существующийDataSet
. После добавления данных ограничения применяются к текущим значениям в объекте DataSet
. Необходимо убедиться, что код обрабатывает все исключения, которые могут быть вызваны из-за нарушений ограничений.
Рассмотрим случай, когда существующая строка в DataSet
строке является строкой Unchanged
со значением первичного ключа 1. Во время операции слияния со Modified
входящей строкой со Original
значением первичного ключа 2 и значением первичного ключа 1 существующая строка и Current
входящая строка не считаются совпадающими, так как Original
значения первичного ключа отличаются. Однако при завершении слияния и проверке ограничений возникает исключение, так как Current
значения первичного ключа нарушают уникальное ограничение для столбца первичного ключа.
Замечание
Если строки вставляются в таблицу базы данных, содержащую столбец с автоматическим увеличением, например столбец идентификатора, значение столбца идентификатора, возвращаемое вставкой, может не совпадать со значением в таблице DataSet
, что приводит к добавлению возвращённых строк вместо их объединения. Дополнительные сведения см. в разделе "Получение значений идентификаторов или автонумеров".
Следующий пример кода объединяет два DataSet
объекта с разными схемами в одну DataSet
с объединенными схемами двух входящих DataSet
объектов.
using (SqlConnection connection =
new(connectionString))
{
SqlDataAdapter adapter =
new(
"SELECT CustomerID, CompanyName FROM dbo.Customers",
connection);
connection.Open();
DataSet customers = new();
adapter.FillSchema(customers, SchemaType.Source, "Customers");
adapter.Fill(customers, "Customers");
DataSet orders = new();
orders.ReadXml("Orders.xml", XmlReadMode.ReadSchema);
orders.AcceptChanges();
customers.Merge(orders, true, MissingSchemaAction.AddWithKey);
}
Using connection As SqlConnection = New SqlConnection(
connectionString)
Dim adapter As New SqlDataAdapter(
"SELECT CustomerID, CompanyName FROM Customers", connection)
connection.Open()
Dim customers As New DataSet()
adapter.FillSchema(customers, SchemaType.Source, "Customers")
adapter.Fill(customers, "Customers")
Dim orders As New DataSet()
orders.ReadXml("Orders.xml", XmlReadMode.ReadSchema)
orders.AcceptChanges()
customers.Merge(orders, True, MissingSchemaAction.AddWithKey)
End Using
Следующий пример кода принимает существующее DataSet
, содержащее обновления, и передает эти обновления DataAdapter
для обработки на уровне источника данных. Затем результаты объединяются в исходный DataSet
. После отклонения изменений, которые привели к ошибке, объединенные изменения фиксируются с AcceptChanges
.
DataTable customers = dataSet.Tables["Customers"]!;
// Make modifications to the Customers table.
// Get changes to the DataSet.
DataSet dataSetChanges = dataSet.GetChanges() ?? new();
// Add an event handler to handle the errors during Update.
adapter.RowUpdated += OnRowUpdated;
connection.Open();
adapter.Update(dataSetChanges, "Customers");
connection.Close();
// Merge the updates.
dataSet.Merge(dataSetChanges, true, MissingSchemaAction.Add);
// Reject changes on rows with errors and clear the error.
DataRow[] errRows = dataSet.Tables["Customers"]!.GetErrors();
foreach (DataRow errRow in errRows)
{
errRow.RejectChanges();
errRow.RowError = null;
}
// Commit the changes.
dataSet.AcceptChanges();
Dim customers As DataTable = dataSet.Tables("Customers")
' Make modifications to the Customers table.
' Get changes to the DataSet.
Dim dataSetChanges As DataSet = dataSet.GetChanges()
' Add an event handler to handle the errors during Update.
AddHandler adapter.RowUpdated, New SqlRowUpdatedEventHandler(
AddressOf OnRowUpdated)
connection.Open()
adapter.Update(dataSetChanges, "Customers")
connection.Close()
' Merge the updates.
dataSet.Merge(dataSetChanges, True, MissingSchemaAction.Add)
' Reject changes on rows with errors and clear the error.
Dim errRows() As DataRow = dataSet.Tables("Customers").GetErrors()
Dim errRow As DataRow
For Each errRow In errRows
errRow.RejectChanges()
errRow.RowError = Nothing
Next
' Commit the changes.
dataSet.AcceptChanges()
protected static void OnRowUpdated(
object sender, SqlRowUpdatedEventArgs args)
{
if (args.Status == UpdateStatus.ErrorsOccurred)
{
args.Row.RowError = args.Errors!.Message;
args.Status = UpdateStatus.SkipCurrentRow;
}
}
Private Sub OnRowUpdated(
ByVal sender As Object, ByVal args As SqlRowUpdatedEventArgs)
If args.Status = UpdateStatus.ErrorsOccurred Then
args.Row.RowError = args.Errors.Message
args.Status = UpdateStatus.SkipCurrentRow
End If
End Sub