Bagikan melalui


Menggabungkan Konten Himpunan Data

Anda dapat menggunakan metode Merge untuk menggabungkan konten larik DataSet, DataTable, atau DataRow ke dalam DataSet yang sudah ada. Beberapa faktor dan opsi memengaruhi bagaimana data baru digabungkan ke dalam DataSet yang sudah ada.

Kunci Primer

Jika tabel yang menerima data dan skema baru dari penggabungan memiliki kunci primer, baris baru dari data masuk dicocokkan dengan baris yang sudah ada yang memiliki nilai kunci primer Original yang sama dengan yang ada di data masuk. Jika kolom dari skema masuk cocok dengan skema yang ada, data dalam baris yang ada dimodifikasi. Kolom yang tidak cocok dengan skema yang sudah ada akan diabaikan atau ditambahkan berdasarkan parameter MissingSchemaAction. Baris baru dengan nilai kunci utama yang tidak cocok dengan baris yang ada ditambahkan ke tabel yang ada.

Jika baris masuk atau baris yang sudah ada memiliki status baris Added, nilai kunci primernya dicocokkan menggunakan nilai kunci primer Current baris Added karena tidak ada versi baris Original.

Jika tabel masuk dan tabel yang sudah ada berisi kolom dengan nama yang sama tetapi jenis data yang berbeda, pengecualian dilemparkan dan peristiwa MergeFailed dari DataSet dinaikkan. Jika tabel masuk dan tabel yang sudah ada memiliki kunci tertentu, tetapi kunci primernya untuk kolom berbeda, pengecualian dilemparkan dan peristiwa MergeFailed dari DataSet dinaikkan.

Jika tabel yang menerima data baru dari gabungan tidak memiliki kunci utama, baris baru dari data yang masuk tidak dapat dicocokkan dengan baris yang ada dalam tabel dan ditambahkan ke tabel yang ada.

Nama Tabel dan Ruang Nama

Objek DataTable dapat secara opsional diberi nilai properti Namespace. Saat nilai Namespace ditetapkan, DataSet dapat berisi beberapa objek DataTable dengan nilai TableName yang sama. Selama operasi penggabungan, TableName dan Namespace digunakan untuk mengidentifikasi target penggabungan. Jika tidak ada Namespace yang ditetapkan, hanya TableName yang digunakan untuk mengidentifikasi target penggabungan.

Catatan

Perilaku ini berubah di versi 2.0 dari .NET Framework. Di versi 1.1, namespaces didukung tetapi diabaikan selama operasi penggabungan. Untuk alasan ini, DataSet yang menggunakan nilai properti Namespace akan memiliki perilaku yang berbeda tergantung pada versi .NET Framework yang Anda jalankan. Misalnya, Anda memiliki dua DataSets berisi DataTables dengan nilai properti TableName yang sama tetapi nilai properti Namespace yang berbeda. Dalam versi 1.1 .NET Framework, nama Namespace yang berbeda akan diabaikan saat menggabungkan dua objek DataSet. Namun, dimulai dengan versi 2.0, penggabungan menyebabkan dua DataTables yang baru dibuat di target DataSet. DataTables aslinya tidak akan terpengaruh penggabungan.

PreserveChanges

Saat Anda meneruskan larik DataSet, DataTable, atau DataRow ke metode Merge, Anda dapat menyertakan parameter opsional yang menentukan apakah akan mempertahankan perubahan yang sudah ada di DataSet atau tidak, dan cara menangani elemen skema baru yang ditemukan dalam data masuk. Parameter pertama setelah data masuk adalah bendera Boolean, PreserveChanges, yang menentukan apakah akan mempertahankan perubahan yang sudah ada di DataSet atau tidak. Jika bendera PreserveChanges diatur ke true, nilai masuk tidak akan menimpa nilai yang sudah ada di versi baris Current dari baris yang sudah ada. Jika bendera PreserveChanges diatur ke false, nilai masuk akan menimpa nilai yang sudah ada di versi baris Current dari baris yang sudah ada. Jika bendera PreserveChanges tidak ditentukan, maka akan diatur ke false secara default. Untuk informasi selengkapnya tentang versi baris, lihat Status Baris dan Versi Baris.

Ketika PreserveChanges adalah true, data dari baris yang sudah ada dipertahankan di versi baris Current dari baris yang sudah ada, sementara data dari versi baris Original dari baris yang sudah ada ditimpa dengan data dari versi baris Original dari baris masuk. RowState dari baris yang sudah ada diatur ke Modified. Pengecualian berikut berlaku:

  • Jika baris yang sudah ada memiliki RowState dari Deleted, RowState ini tetap Deleted ada dan tidak diatur ke Modified. Dalam hal ini, data dari baris masuk masih akan disimpan dalam versi baris Original dari baris yang sudah ada, menimpa versi baris Original dari baris yang sudah ada (kecuali baris masuk memiliki RowState dari Added).

  • Jika baris masuk memiliki RowState dari Added, data dari versi baris Original dari baris yang sudah ada tidak akan ditimpa dengan data dari baris masuk, karena baris masuk tidak memiliki versi baris Original.

Ketika PreserveChanges adalah false, baik versi baris Current dan Original di baris yang sudah ada ditimpa dengan data dari baris masuk, dan RowState baris yang sudah ada diatur ke RowState dari baris masuk. Pengecualian berikut berlaku:

  • Jika baris masuk memiliki RowState dari Unchanged dan baris yang sudah ada memiliki RowState dari Modified, Deleted, atau Added, RowState dari baris yang sudah ada diatur ke Modified.

  • Jika baris masuk memiliki RowState dari Added dan baris yang sudah ada memiliki RowState dari Unchanged, Modified, atau Deleted, RowState dari baris yang sudah ada diatur ke Modified. Selain itu, data dari versi baris Original dari baris yang sudah ada tidak ditimpa dengan data dari baris masuk, karena baris masuk tidak memiliki versi baris Original.

MissingSchemaAction

Anda dapat menggunakan parameter opsional MissingSchemaAction dari metode Merge untuk menentukan bagaimana Merge akan menangani elemen skema di data masuk yang bukan bagian dari DataSet yang sudah ada.

Tabel berikut menjelaskan opsi untuk MissingSchemaAction.

Opsi MissingSchemaAction Deskripsi
Add Tambahkan informasi skema baru ke DataSet dan isi kolom baru dengan nilai masuk. Ini adalah default.
AddWithKey Tambahkan informasi skema baru dan kunci primer ke DataSet dan isi kolom baru dengan nilai masuk.
Error Lemparkan pengecualian jika informasi skema yang tidak cocok ditemui.
Ignore Abaikan informasi skema baru.

Kendala

Dengan metode Merge, batasan tidak diperiksa sampai semua data baru telah ditambahkan ke DataSet yang sudah ada. Setelah data ditambahkan, batasan diberlakukan pada nilai saat ini di DataSet. Anda harus memastikan bahwa kode Anda menangani pengecualian apa pun yang mungkin dilemparkan karena pelanggaran batasan.

Pertimbangkan kasus di mana baris yang sudah ada dalam DataSet adalah baris Unchanged dengan nilai kunci primer 1. Selama operasi penggabungan dengan baris masuk Modified dengan Original yang nilai kunci primernya 2 dan Current yang nilai kunci primernya 1, baris yang sudah ada dan baris masuk tidak dianggap cocok karena nilai kunci utama Original berbeda. Namun, ketika penggabungan selesai dan batasan diperiksa, pengecualian akan dilemparkan karena nilai kunci primer Current melanggar batasan unik untuk kolom kunci primer.

Catatan

Saat baris disisipkan ke dalam tabel database yang berisi kolom peningkatan otomatis seperti kolom identitas, nilai kolom identitas yang dikembalikan oleh sisipan mungkin tidak cocok dengan nilai dalam DataSet, menyebabkan baris yang dikembalikan ditambahkan alih-alih digabungkan. Untuk informasi selengkapnya, lihat Mengambil Nilai Identitas atau Autonumber.

Contoh kode berikut menggabungkan dua objek DataSet dengan skema yang berbeda menjadi satu DataSet dengan skema gabungan dari dua objek DataSet yang masuk.

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

Contoh kode berikut mengambil DataSet yang sudah ada dengan pembaruan dan meneruskan pembaruan tersebut ke DataAdapter yang akan diproses di sumber data. Hasilnya kemudian digabungkan ke dalam aslinya DataSet. Setelah menolak perubahan yang mengakibatkan kesalahan, perubahan yang digabungkan diterapkan dengan 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

Lihat juga