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 Zeile Deleted lautet, bleibt dieser RowState als Deleted erhalten und wird nicht auf Modified festgelegt. In diesem Fall werden die Daten aus der empfangenen Zeile immer noch in der Zeilenversion Original der vorhandenen Zeile gespeichert, wobei die Zeilenversion Original der vorhandenen Zeile überschrieben wird (es sei denn, der RowState der empfangenen Zeile lautet Added).

  • Wenn der RowState der empfangenen Zeile Added lautet, werden die Daten aus der Original-Zeilenversion der vorhandenen Zeile nicht mit den Daten der empfangenen Zeile überschrieben, weil die empfangene Zeile keine Original-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 RowStateUnchanged und die vorhandene Zeile den RowStateModified, Deleted oder Added besitzt, wird der RowState der vorhandenen Zeile auf Modified festgelegt.

  • Wenn die empfangene Zeile den RowStateAdded und die vorhandene Zeile den RowStateUnchanged, Modified oder Deleted besitzt, wird der RowState der vorhandenen Zeile auf Modified festgelegt. Außerdem werden die Daten der Original-Zeilenversion der vorhandenen Zeile nicht durch die Daten der empfangenen Zeile überschrieben, weil die empfangene Zeile keine Original-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

Siehe auch