Udostępnij za pośrednictwem


Scalanie zawartości zestawu danych

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

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 Added wiersza, ich wartości kluczowe są dopasowywane za pomocą Current wartości klucza podstawowego Added wiersza, ze względu na brak Original wersji wiersza.

Jeśli tabela przychodząca i istniejąca tabela zawierają kolumnę o tej samej nazwie, ale różnych typach danych, zgłaszany jest wyjątek, a zdarzenie MergeFailed jest uruchamiane z DataSet. Jeśli zarówno tabela przychodząca, jak i istniejąca tabela mają zdefiniowane klucze, ale klucze podstawowe dotyczą różnych kolumn, zgłaszany jest wyjątek, a zdarzenie MergeFailed jest podnoszone dla 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

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

Uwaga / Notatka

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, który używa wartości właściwości Namespace, będzie się zachowywać inaczej, w zależności od wersji używanego programu .NET Framework. Załóżmy na przykład, że masz dwa DataSets zawierające DataTables o tych samych wartościach właściwości TableName, ale o różnych wartościach właściwości Namespace. 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 DataTables w obiekcie docelowym DataSet. Oryginalny element DataTables nie będzie mieć wpływu na scalanie.

Zachowaj zmiany

Przy przekazaniu tablic DataSet, DataTable lub DataRow do metody Merge można uwzględnić opcjonalne parametry określające, czy zachować zmiany w istniejącym DataSet oraz jak obsługiwać nowe elementy schematu znalezione w danych przychodzących. Pierwszy z tych parametrów, z danych przychodzących, jest flagą logiczną PreserveChanges, która określa, czy zachować zmiany w istniejącym DataSet. 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 PreserveChanges jest ustawiona na false, wartości przychodzące zastępują istniejące wartości w wersji wiersza Current. Jeśli flaga PreserveChanges nie jest określona, jest domyślnie ustawiona na false. Aby uzyskać więcej informacji na temat wersji wierszy, zobacz Row States and Row Versions (Stany wierszy i wersje wierszy).

Gdy PreserveChanges jest true, dane z istniejącego wiersza są przechowywane w Current wersji tego wiersza, podczas gdy dane z Original wersji tego wiersza są zastępowane danymi z Original wersji nadchodzącego wiersza. Wartość RowState istniejącego wiersza jest ustawiona na Modified. Stosuje się następujące wyjątki:

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

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

Gdy PreserveChanges jest false, zarówno wersje wiersza Current i Original w istniejącym wierszu są zastępowane danymi z wiersza przychodzącego, a RowState istniejącego wiersza jest ustawiany na RowState wiersza przychodzącego. Stosuje się następujące wyjątki:

  • Jeśli wiersz przychodzący ma RowState o wartości Unchanged, a istniejący wiersz ma RowState o wartości Modified, Deleted lub Added, ustaw RowState istniejącego wiersza na Modified.

  • Jeśli wiersz przychodzący ma wartość RowState, a istniejący wiersz ma wartość Added, RowState, Unchanged lub Modified, wartość Deleted dla istniejącego wiersza jest ustawiona na RowState. 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 parametru MissingSchemaAction metody Merge, aby określić sposób, w jaki Merge będzie obsługiwać elementy schematu w danych przychodzących, które nie są częścią istniejącego DataSet.

W poniższej tabeli opisano opcje programu MissingSchemaAction.

Opcja MissingSchemaAction Opis
Add Dodaj nowe informacje o schemacie do DataSet elementu i wypełnij nowe kolumny wartościami przychodzącymi. Jest to wartość domyślna.
AddWithKey Dodaj nowy schemat oraz informacje o kluczu podstawowym do DataSet i wypełnij nowe kolumny wartością przychodzącymi.
Error Zgłoś wyjątek, gdy zidentyfikowane zostaną niezgodne informacje o schemacie.
Ignore Ignoruj nowe informacje o schemacie.

Ograniczenia

Metoda Merge powoduje, że ograniczenia nie są sprawdzane, dopóki wszystkie nowe dane nie zostaną dodane do istniejącego DataSet. 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 tabeli DataSet jest wierszem typu Unchanged z wartością klucza podstawowego równą 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 / Notatka

Gdy wstawiane są wiersze do tabeli bazy danych z kolumną automatycznie zwiększaną, taką jak kolumna identyfikatorów, wartość tej kolumny zwrócona przez operację może nie odpowiadać wartości w DataSet tabeli, co powoduje dodanie zwracanych wierszy zamiast ich scalania. Aby uzyskać więcej informacji, zobacz Pobieranie identyfikatorów lub wartości automatycznego numerowania.

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 z aktualizacjami i przekazuje te aktualizacje do DataAdapter w celu przetworzenia w źródle danych. Wyniki są następnie łączone z oryginalnym elementem DataSet. 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 także