Freigeben über


Zusammenführen von DataSet-Inhalten

Mit der Merge Methode können Sie den Inhalt eines DataSet, DataTable oder DataRow Arrays in ein bestehendes DataSet zusammenführen. Mehrere Faktoren und Optionen wirken sich darauf aus, wie neue Daten in einem vorhandenen DataSetzusammengeführt werden.

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 eingehenden 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 entweder ignoriert oder basierend auf dem MissingSchemaAction Parameter hinzugefügt. Neue Zeilen mit Primärschlüsselwerten, die keiner vorhandenen Zeile entsprechen, werden an die vorhandene Tabelle angefügt.

Wenn eingehende oder vorhandene Zeilen einen Zeilenstatus Addedaufweisen, werden die Primärschlüsselwerte mit dem Current Primärschlüsselwert der Added Zeile abgeglichen, da keine Original Zeilenversion vorhanden ist.

Wenn eine eingehende Tabelle und eine vorhandene Tabelle eine Spalte mit demselben Namen, aber unterschiedliche Datentypen enthalten, wird eine Ausnahme ausgelöst, und das MergeFailed Ereignis der DataSet Tabelle wird ausgelöst. Wenn eine eingehende Tabelle und eine vorhandene Tabelle beide Schlüssel definiert haben, die Primärschlüssel jedoch für unterschiedliche Spalten gelten, wird eine Ausnahme ausgelöst, und das MergeFailed Ereignis der DataSet Tabelle wird ausgelöst.

Wenn die Tabelle, die neue Daten aus einer Datenzusammenführung empfängt, keinen Primärschlüssel aufweist, können neue Zeilen aus den eingehenden Daten nicht mit vorhandenen Zeilen in der Tabelle abgeglichen werden und werden stattdessen an die vorhandene Tabelle angefügt.

Tabellennamen und Namespaces

DataTable Objekten kann optional ein Namespace Eigenschaftswert zugewiesen werden. Wenn Namespace Werten zugewiesen werden, kann ein DataSet Objekt mehrere DataTable Objekte mit demselben TableName Wert enthalten. Bei Zusammenführungsvorgängen werden sowohl TableName als auch Namespace verwendet, um das Ziel einer Zusammenführung zu identifizieren. Wenn kein Namespace zugewiesen wurde, dient nur das TableName dazu, das Ziel einer Zusammenführung zu identifizieren.

Hinweis

Dieses Verhalten wurde in Version 2.0 von .NET Framework geändert. In Version 1.1 wurden Namespaces unterstützt, während der Zusammenführungsvorgänge jedoch ignoriert. Aus diesem Grund kann ein DataSet, das Namespace Eigenschaftswerte verwendet, unterschiedliche Verhaltensmuster aufweisen, je nachdem, welche Version von dem .NET Framework ausgeführt wird. Nehmen wir z. B. an, es gibt zwei DataSets, die DataTables mit identischen TableName-Eigenschaftswerten, aber verschiedenen Namespace-Eigenschaftswerten enthalten. In Version 1.1 von .NET Framework werden die verschiedenen Namespace Namen beim Zusammenführen der beiden DataSet Objekte ignoriert. Ab Version 2.0 werden beim Zusammenführen jedoch zwei neue DataTables im Ziel DataSet erstellt. Das Original DataTables wird von der Zusammenführung nicht beeinflusst.

PreserveChanges

Wenn Sie ein DataSet, DataTable oder DataRow Array an die Merge-Methode übergeben, können Sie optionale Parameter angeben, die festlegen, ob Änderungen im vorhandenen DataSet beibehalten werden sollen und wie neue Schemaelemente behandelt werden, die in den eingehenden Daten gefunden werden. Der erste dieser Parameter nach den eingehenden Daten ist ein boolesches Flag, PreserveChanges, das angibt, ob die Änderungen in der vorhandenen DataSet erhalten oder nicht erhalten bleiben sollen. Wenn das PreserveChanges Kennzeichen auf true festgelegt ist, überschreiben neue Werte keine bestehenden Werte in der Current-Version der vorhandenen Zeile. 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 die PreserveChanges Flag nicht angegeben ist, wird es standardmäßig auf false festgelegt. Weitere Informationen zu Zeilenversionen 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. Die vorhandene Zeile RowState ist auf Modified festgelegt. Beachten Sie folgende Ausnahmen:

  • Wenn die bestehende Zeile einen RowState von Deleted hat, bleibt RowState auf Deleted bestehen und wird nicht auf Modified gesetzt. 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 eingehende Zeile eine RowState von Unchanged hat und die vorhandene Zeile einen RowState von Modified, Deleted oder Added besitzt, wird die RowState der vorhandenen Zeile auf Modified festgelegt.

  • Wenn die eingehende Zeile eine RowState von Added hat und die vorhandene Zeile eine RowState von Unchanged, Modified oder Deleted hat, wird die RowState der vorhandenen Zeile auf Modified festgelegt. Außerdem werden die Daten aus der Original Zeilenversion der vorhandenen Zeile nicht mit Daten aus der eingehenden Zeile überschrieben, da die eingehende Zeile keine Original Zeilenversion enthält.

MissingSchemaAction

Mit dem optionalen MissingSchemaAction Parameter der Merge Methode können Sie angeben, wie Merge Schemaelemente in den eingehenden Daten behandelt werden, die nicht Teil der vorhandenen DataSetDaten sind.

In der folgenden Tabelle sind die Optionen für MissingSchemaAction beschrieben.

MissingSchemaAction-Option BESCHREIBUNG
Add Fügen Sie die neuen Schemainformationen zu DataSet hinzu und füllen Sie die neuen Spalten mit den eingehenden Werten. Dies ist die Standardeinstellung.
AddWithKey Fügen Sie die neuen Schema- und Primärschlüsselinformationen zu DataSet hinzu und befüllen Sie die neuen Spalten mit den eingehenden Werten.
Error Werfen Sie eine Ausnahme, wenn inkongruente Schemainformationen gefunden werden.
Ignore Ignorieren Sie die neuen Schemainformationen.

Zwänge

Mit der Merge Methode werden Einschränkungen erst überprüft, wenn alle neuen Daten dem vorhandenen DataSethinzugefügt wurden. Mit dem Hinzufügen der Daten werden Einschränkungen für die aktuellen Werte in der DataSet durchgesetzt. Sie müssen sicherstellen, dass Ihr Code alle möglichen Ausnahmen behandelt, die aufgrund von Einschränkungsverletzungen geworfen werden können.

Betrachten wir den Fall, in dem eine vorhandene Zeile in einer DataSet eine Unchanged-Zeile mit einem Primärschlüsselwert von 1 ist. Bei einem Zusammenführungsvorgang mit einer Modified eingehenden Zeile mit einem Original Primärschlüsselwert von 2 und einem Current Primärschlüsselwert von 1 werden die vorhandene Zeile und die eingehende Zeile nicht als übereinstimmend betrachtet, da sich die Original Primärschlüsselwerte unterscheiden. Wenn die Zusammenführung abgeschlossen ist und Einschränkungen überprüft werden, wird jedoch eine Ausnahme ausgelöst, da die Current Primärschlüsselwerte gegen die eindeutige Einschränkung für die Primärschlüsselspalte verstoßen.

Hinweis

Wenn Zeilen in eine Datenbanktabelle eingefügt werden, die eine automatische Inkrementierungsspalte wie eine Identitätsspalte enthält, entspricht der vom Einfügen zurückgegebene Identitätsspaltenwert möglicherweise nicht dem Wert in der DataSetDatenbanktabelle, wodurch die zurückgegebenen Zeilen angefügt werden, anstatt zusammengeführt zu werden. Weitere Informationen finden Sie unter Abrufen von Identitäts- oder Autonummernwerten.

Im folgenden Codebeispiel werden zwei DataSet Objekte mit unterschiedlichen Schemas in einem DataSet mit den kombinierten Schemas der beiden eingehenden 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 wird ein vorhandenes DataSet mit Updates versehen, und diese Aktualisierungen werden an ein DataAdapter zur Verarbeitung an der Datenquelle übergeben. Die Ergebnisse werden dann mit dem Original DataSetzusammengeführt. Nach dem Ablehnen von Änderungen, die zu einem Fehler geführt haben, werden die zusammengeführten Änderungen mit AcceptChanges festgeschrieben.

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