Zusammenführen von DataSet-Inhalten
Sie können die Merge-Methode verwenden, um den Inhalt eines DataSet-, DataTable- oder DataRow-Arrays in einem vorhandenen DataSet
zusammenzuführen. Wie die neuen Daten in einem vorhandenen DataSet
zusammengeführt werden, hängt von mehreren Faktoren und Optionen ab.
Primärschlüssel
Wenn die Tabelle, die neue Daten und Schemas aus einem Merge empfängt, einen Primärschlüssel besitzt, werden die neuen Zeilen aus den empfangenen Daten mit vorhandenen Zeilen verglichen, die dieselben Original-Primärschlüsselwerte besitzen wie die empfangenen Daten. Wenn die Spalten aus dem empfangenen Schema mit denen des vorhandenen Schemas übereinstimmen, werden die Daten in den vorhandenen Zeilen geändert. Spalten, die nicht mit dem vorhandenen Schema übereinstimmen, werden, abhängig vom Wert des MissingSchemaAction-Parameters, entweder ignoriert oder hinzugefügt. Neue Zeilen mit Primärschlüsselwerten, die nicht mit vorhandenen Zeilen übereinstimmen, werden an die vorhandene Tabelle angehängt.
Wenn empfangene oder vorhandene Zeilen den Zeilenstatus Added aufweisen, werden ihre Primärschlüsselwerte mit dem Current-Primärschlüsselwert der Added
-Zeile verglichen, weil es keine Original
-Zeilenversion gibt.
Wenn eine empfangene Tabelle und eine vorhandene Tabelle eine Spalte mit demselben Namen, aber unterschiedlichen Datentypen enthalten, wird eine Ausnahme generiert, und das MergeFailed-Ereignis des DataSet
wird ausgelöst. Wenn sowohl eine empfangene Tabelle als auch eine vorhandene Tabelle definierte Primärschlüssel besitzen, die Primärschlüssel aber für verschiedene Spalten gelten, wird eine Ausnahme generiert und das MergeFailed
-Ereignis des DataSet
ausgelöst.
Wenn die Tabelle, die neue Daten aus einer Zusammenführung empfängt, keinen Primärschlüssel besitzt, können die neuen Zeilen aus den empfangenen Daten nicht mit vorhandenen Zeilen in der Tabelle verglichen werden. Die Zeilen werden dann stattdessen an die vorhandene Tabelle angehängt.
Tabellennamen und Namespaces
DataTable-Objekten kann optional ein Namespace-Eigenschaftswert zugewiesen werden. Wenn Namespace-Werte zugewiesen werden, kann ein DataSet mehrere DataTable-Objekte mit demselben TableName-Wert enthalten. Bei Merges werden sowohl der TableName als auch der Namespace verwendet, um das Ziel des Merge anzugeben. Wenn kein Namespace zugewiesen wurde, wird zur Angabe des Ziels nur der TableName verwendet.
Hinweis
Dieses Verhalten ist in .NET Framework 2.0 neu. In Version 1.1 wurden Namespaces zwar unterstützt, bei Merges wurden sie aber ignoriert. Aus diesem Grund hängt das Verhalten eines DataSet, das Namespace-Eigenschaftswerte verwendet, von der jeweils verwendeten .NET Framework-Version ab. Nehmen wir z. B. an, es gibt zwei DataSets
, die DataTables
mit identischen TableName-Eigenschaftswerten, aber verschiedenen Namespace-Eigenschaftswerten enthalten. In .NET Framework 1.1 werden die verschiedenen Namespace-Namen beim Zusammenführen der beiden DataSet-Objekte ignoriert. Ab Version 2.0 hingegen werden beim Zusammenführen zwei neue DataTables
im Ziel-DataSet erstellt. Auf die ursprünglichen DataTables
hat die Zusammenführung keine Auswirkung.
PreserveChanges
Wenn Sie ein DataSet
-, ein DataTable
- oder ein DataRow
-Array an die Merge
-Methode übergeben, können Sie mit optionalen Parametern angeben, ob Änderungen im vorhandenen DataSet
beibehalten werden sollen und wie die neuen Schemaelemente in den empfangenen Daten zu behandeln sind. Der erste dieser Parameter nach den empfangenen Daten ist ein Boolean-Flag, PreserveChanges, das angibt, ob die Änderungen im vorhandenen DataSet
beibehalten werden sollen. Wenn das PreserveChanges
-Flag auf true
festgelegt ist, werden vorhandene Werte in der Current
-Zeilenversion der vorhandenen Zeile nicht durch die empfangenen Werte überschrieben. Wenn das PreserveChanges
-Flag auf false
festgelegt ist, werden die vorhandenen Werte in der Current
-Zeilenversion der vorhandenen Zeile mit den empfangenen Werten überschrieben. Wenn für das PreserveChanges
-Flag nichts angegeben wird, wird es standardmäßig auf false
festgelegt. Weitere Informationen finden Sie unter Zeilenzustände und Zeilenversionen.
Wenn das PreserveChanges
-Flag auf true
festgelegt ist, werden die Daten der vorhandenen Zeile in der Current-Zeilenversion der vorhandenen Zeile beibehalten, während die Daten aus der Original-Zeilenversion der vorhandenen Zeile durch die Daten aus der Original
-Zeilenversion der empfangenen Zeile überschrieben werden. Der RowState der vorhandenen Zeile wird auf Modified festgelegt. Beachten Sie folgende Ausnahmen:
Wenn der
RowState
der vorhandenen ZeileDeleted
lautet, bleibt dieserRowState
alsDeleted
erhalten und wird nicht aufModified
festgelegt. In diesem Fall werden die Daten aus der empfangenen Zeile immer noch in der ZeilenversionOriginal
der vorhandenen Zeile gespeichert, wobei die ZeilenversionOriginal
der vorhandenen Zeile überschrieben wird (es sei denn, derRowState
der empfangenen Zeile lautetAdded
).Wenn der
RowState
der empfangenen ZeileAdded
lautet, werden die Daten aus derOriginal
-Zeilenversion der vorhandenen Zeile nicht mit den Daten der empfangenen Zeile überschrieben, weil die empfangene Zeile keineOriginal
-Zeilenversion besitzt.
Wenn das PreserveChanges
-Flag auf false
festgelegt ist, werden sowohl die Current
-Zeilenversion als auch die Original
-Zeilenversion in der vorhandenen Zeile durch die Daten der empfangenen Zeile überschrieben, und der RowState
der vorhandenen Zeile wird auf den RowState
der empfangenen Zeile festgelegt. Beachten Sie folgende Ausnahmen:
Wenn die empfangene Zeile den
RowState
Unchanged
und die vorhandene Zeile denRowState
Modified
,Deleted
oderAdded
besitzt, wird derRowState
der vorhandenen Zeile aufModified
festgelegt.Wenn die empfangene Zeile den
RowState
Added
und die vorhandene Zeile denRowState
Unchanged
,Modified
oderDeleted
besitzt, wird derRowState
der vorhandenen Zeile aufModified
festgelegt. Außerdem werden die Daten derOriginal
-Zeilenversion der vorhandenen Zeile nicht durch die Daten der empfangenen Zeile überschrieben, weil die empfangene Zeile keineOriginal
-Zeilenversion besitzt.
MissingSchemaAction
Mit dem optionalen MissingSchemaAction-Parameter der Merge
-Methode können Sie angeben, wie die Merge
-Methode Schemaelemente in den empfangenen Daten behandeln soll, die nicht Teil des bestehenden DataSet
sind.
Eine Beschreibung der Optionen für MissingSchemaAction
finden Sie in der folgenden Tabelle.
MissingSchemaAction-Option | BESCHREIBUNG |
---|---|
Add | Fügt dem DataSet die neuen Schemainformationen hinzu und füllt die neuen Spalten mit den empfangenen Werten auf. Dies ist die Standardoption. |
AddWithKey | Fügt dem DataSet die neuen Schema- und Primärschlüsselinformationen hinzu und füllt die neuen Spalten mit den empfangenen Werten auf. |
Error | Auslösen einer Ausnahme, wenn nicht übereinstimmende Schemainformationen gefunden werden. |
Ignore | Ignorieren der neuen Schemainformationen. |
Einschränkungen
Bei der Merge
-Methode werden Einschränkungen erst überprüft, wenn dem vorhandenen DataSet
alle neuen Daten hinzugefügt wurden. Sobald die Daten hinzugefügt wurden, werden die Einschränkungen für die aktuellen Werte im DataSet
erzwungen. Sie müssen sicherstellen, dass Ihr Code die Behandlung von Ausnahmen ermöglicht, die aufgrund von Einschränkungsverletzungen ausgelöst werden.
Nehmen wir einmal an, eine vorhandene Zeile in einem DataSet
ist eine Zeile mit dem Unchanged
-Zeilenstatus und dem Primärschlüsselwert 1. Beim Zusammenführen mit einer empfangenen Zeile mit dem Modified
-Zeilenstatus und dem Original
-Primärschlüsselwert 2 sowie dem Current
-Primärschlüsselwert 1 werden die vorhandene Zeile und die empfangene Zeile als nicht übereinstimmend betrachtet, weil die Original
-Primärschlüsselwerte unterschiedlich sind. Wenn die Zusammenführung abgeschlossen ist und die Einschränkungen überprüft werden, wird allerdings eine Ausnahme ausgelöst, weil die Current
-Primärschlüsselwerte die <legacyBold>Unique</legacyBold>-Einschränkung für die Primärschlüsselspalte verletzen.
Hinweis
Beim Einfügen von Zeilen in Datenbanktabellen mit automatisch inkrementierenden Spalten, z. B. Identitätsspalten, ist es möglich, dass der von der Einfügung zurückgegebene Wert für die Identitätsspalte nicht mit dem Wert im DataSet
übereinstimmt, sodass die zurückgegebenen Zeilen nicht zusammengeführt, sondern angefügt werden. Weitere Informationen finden Sie unter Abrufen von Identität oder AutoWert.
Im folgenden Codebeispiel werden zwei DataSet
-Objekte mit verschiedenen Schemas in einem DataSet
mit den kombinierten Schemas der beiden empfangenen DataSet
-Objekte zusammengeführt.
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
Im folgenden Codebeispiel gibt es ein vorhandenes DataSet
mit Updates, die an einen DataAdapter
übergeben werden, der an der Datenquelle verarbeitet werden soll. Die Ergebnisse werden anschließend im ursprünglichen DataSet
zusammengeführt. Nachdem die Änderungen zurückgewiesen wurden, die zu einem Fehler führten, wird mit AcceptChanges
ein Commit für die zusammengeführten Änderungen ausgeführt.
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