Scalanie zawartości elementu DataSet

Za pomocą Merge metody można scalić zawartość tablicy DataSet, DataTablelub DataRow z istniejącą DataSettablicą . Kilka czynników i opcji wpływa na sposób scalania nowych danych z istniejącym DataSetelementem .

Klucze podstawowe

Jeśli tabela odbierającą nowe dane i schemat z scalania ma klucz podstawowy, nowe wiersze z danych przychodzących są zgodne z istniejącymi wierszami, które mają te same Original wartości klucza podstawowego co te w danych przychodzących. Jeśli kolumny ze schematu przychodzącego są zgodne z tymi z istniejącego schematu, dane w istniejących wierszach zostaną zmodyfikowane. Kolumny, które nie pasują do istniejącego schematu, są ignorowane lub dodawane na podstawie parametru MissingSchemaAction . Nowe wiersze z wartościami klucza podstawowego, które nie pasują do żadnych istniejących wierszy, są dołączane do istniejącej tabeli.

Jeśli przychodzące lub istniejące wiersze mają stan Addedwiersza , ich wartości klucza podstawowego są dopasowywane przy użyciu Current wartości klucza podstawowego Added wiersza, ponieważ nie Original istnieje żadna wersja wiersza.

Jeśli tabela przychodząca i istniejąca tabela zawierają kolumnę o tej samej nazwie, ale różne typy danych, zgłaszany jest wyjątek i MergeFailed zgłaszane jest zdarzenie DataSet . Jeśli zarówno tabela przychodząca, jak i istniejąca tabela mają zdefiniowane klucze, ale klucze podstawowe są przeznaczone dla różnych kolumn, zgłaszany jest wyjątek i MergeFailed zgłaszane jest zdarzenie DataSet .

Jeśli tabela odbieraca nowe dane ze scalania nie ma klucza podstawowego, nowe wiersze z danych przychodzących nie mogą być dopasowane do istniejących wierszy w tabeli i są zamiast tego dołączane do istniejącej tabeli.

Nazwy tabel i przestrzenie nazw

DataTable obiekty można opcjonalnie przypisać Namespace wartość właściwości. Po Namespace przypisaniu DataSet wartości może zawierać wiele DataTable obiektów o tej samej TableName wartości. Podczas operacji scalania są używane zarówno TableNameNamespace do identyfikowania celu scalania. Jeśli nie Namespace zostało przypisane, tylko TableName element jest używany do identyfikowania celu scalania.

Uwaga

To zachowanie zmieniło się w wersji 2.0 programu .NET Framework. W wersji 1.1 przestrzenie nazw były obsługiwane, ale były ignorowane podczas operacji scalania. Z tego powodu DataSet użycie Namespace wartości właściwości będzie miało różne zachowania w zależności od używanej wersji programu .NET Framework. Załóżmy na przykład, że masz dwa DataSets zawierające DataTables te same TableName wartości właściwości, ale różne Namespace wartości właściwości. W wersji 1.1 programu .NET Framework różne Namespace nazwy będą ignorowane podczas scalania dwóch DataSet obiektów. Jednak począwszy od wersji 2.0 scalanie powoduje utworzenie dwóch nowych w DataTables obiekcie docelowym DataSet. Oryginalny element DataTables nie będzie mieć wpływu na scalanie.

Preservechanges

Po przekazaniu DataSetmetody , DataTablelub DataRow tablicy do Merge metody można uwzględnić opcjonalne parametry określające, czy zachować zmiany w istniejącym DataSetobiekcie oraz jak obsługiwać nowe elementy schematu znalezione w danych przychodzących. Pierwszy z tych parametrów po danych przychodzących jest flagą logiczną , która określa, PreserveChangesczy zachować zmiany w istniejącym DataSetobiekcie . Jeśli flaga PreserveChanges jest ustawiona na true, wartości przychodzące nie zastępują istniejących wartości w Current wersji wiersza istniejącego wiersza. Jeśli flaga jest ustawiona PreserveChanges na false, wartości przychodzące zastępują istniejące wartości w Current wersji wiersza istniejącego wiersza. Jeśli flaga nie jest określona PreserveChanges , jest ustawiona na false wartość domyślną. Aby uzyskać więcej informacji na temat wersji wierszy, zobacz Row States and Row Versions (Stany wierszy i wersje wierszy).

Gdy PreserveChanges wartość to true, dane z istniejącego wiersza są przechowywane w Current wersji wiersza istniejącego wiersza, podczas gdy dane z Original wersji wiersza istniejącego wiersza są zastępowane danymi z Original wersji wiersza przychodzącego wiersza. Dla RowState istniejącego wiersza ustawiono wartość Modified. Stosuje się następujące wyjątki:

  • Jeśli istniejący wiersz ma RowState wartość Deleted, pozostaje Deleted on RowState ustawiony na Modifiedwartość . W takim przypadku dane z wiersza przychodzącego będą nadal przechowywane w Original wersji wiersza istniejącego wiersza, zastępując Original wersję wiersza istniejącego wiersza (chyba że wiersz przychodzący ma RowState wartość Added).

  • Jeśli wiersz przychodzący ma RowState wartość Added, dane z Original wersji wiersza istniejącego wiersza nie zostaną zastąpione danymi z wiersza przychodzącego, ponieważ wiersz przychodzący nie ma Original wersji wiersza.

Gdy PreserveChanges wartość to false, wersje Current wierszy i Original w istniejącym wierszu są zastępowane danymi z wiersza przychodzącego, a istniejący RowState wiersz jest ustawiony na RowState wiersz przychodzący. Stosuje się następujące wyjątki:

  • Jeśli wiersz przychodzący ma wartość , RowStateUnchanged a istniejący wiersz ma RowStateModifiedwartość , Deletedlub Added, RowState dla istniejącego wiersza ustawiono wartość Modified.

  • Jeśli wiersz przychodzący ma RowState wartość , a istniejący wiersz ma UnchangedRowState wartość , Modifiedlub Deleted, RowState dla istniejącego wiersza ustawiono wartość ModifiedAdded. Ponadto dane z Original wersji wiersza istniejącego wiersza nie są zastępowane danymi z wiersza przychodzącego, ponieważ wiersz przychodzący nie ma Original wersji wiersza.

Missingschemaaction

Możesz użyć opcjonalnego MissingSchemaAction parametru Merge metody, aby określić sposób Merge obsługi elementów schematu w danych przychodzących, które nie są częścią istniejącego DataSetelementu .

W poniższej tabeli opisano opcje programu MissingSchemaAction.

MissingSchemaAction, opcja opis
Add Dodaj nowe informacje o schemacie do DataSet elementu i wypełnij nowe kolumny wartościami przychodzącymi. Jest to opcja domyślna.
AddWithKey Dodaj nowy schemat i informacje o kluczu DataSet podstawowym do elementu i wypełnij nowe kolumny wartościami przychodzącymi.
Error Zgłaszanie wyjątku w przypadku napotkania niezgodnych informacji o schemacie.
Ignore Ignoruj nowe informacje o schemacie.

Ograniczenia

W przypadku Merge metody ograniczenia nie są sprawdzane, dopóki wszystkie nowe dane nie zostaną dodane do istniejącego DataSetelementu . Po dodaniu danych ograniczenia są wymuszane dla bieżących wartości w pliku DataSet. Należy się upewnić, że kod obsługuje wszelkie wyjątki, które mogą zostać zgłoszone z powodu naruszeń ograniczeń.

Rozważmy przypadek, w którym istniejący wiersz w obiekcie DataSet to Unchanged wiersz z wartością klucza podstawowego 1. Podczas operacji scalania z wierszem przychodzącym Modified z wartością Original klucza podstawowego 2 i wartością Current klucza podstawowego 1 istniejący wiersz i wiersz przychodzący nie są uznawane za zgodne, ponieważ Original wartości klucza podstawowego różnią się. Jednak po zakończeniu scalania i sprawdzeniu ograniczeń zostanie zgłoszony wyjątek, ponieważ Current wartości klucza podstawowego naruszają unikatowe ograniczenie dla kolumny klucza podstawowego.

Uwaga

Gdy wiersze są wstawiane do tabeli bazy danych zawierającej kolumnę automatycznego zwiększania, taką jak kolumna tożsamości, wartość kolumny tożsamości zwrócona przez wstawianie może nie odpowiadać wartości w DataSettabeli , co powoduje dołączenie zwracanych wierszy zamiast scalania. Aby uzyskać więcej informacji, zobacz Pobieranie tożsamości lub wartości autonumerowania.

Poniższy przykład kodu scala dwa DataSet obiekty z różnymi schematami w jeden DataSet ze połączonymi schematami dwóch obiektów przychodzących 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

Poniższy przykład kodu przyjmuje istniejący DataSet element z aktualizacjami i przekazuje te aktualizacje do DataAdapter przetworzenia w źródle danych. Wyniki zostaną następnie scalone z oryginalnym DataSetelementem . Po odrzuceniu zmian, które spowodowały błąd, scalone zmiany są zatwierdzane za pomocą polecenia 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

Zobacz też