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
dariDeleted
,RowState
ini tetapDeleted
ada dan tidak diatur keModified
. Dalam hal ini, data dari baris masuk masih akan disimpan dalam versi barisOriginal
dari baris yang sudah ada, menimpa versi barisOriginal
dari baris yang sudah ada (kecuali baris masuk memilikiRowState
dariAdded
).Jika baris masuk memiliki
RowState
dariAdded
, data dari versi barisOriginal
dari baris yang sudah ada tidak akan ditimpa dengan data dari baris masuk, karena baris masuk tidak memiliki versi barisOriginal
.
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
dariUnchanged
dan baris yang sudah ada memilikiRowState
dariModified
,Deleted
, atauAdded
,RowState
dari baris yang sudah ada diatur keModified
.Jika baris masuk memiliki
RowState
dariAdded
dan baris yang sudah ada memilikiRowState
dariUnchanged
,Modified
, atauDeleted
,RowState
dari baris yang sudah ada diatur keModified
. Selain itu, data dari versi barisOriginal
dari baris yang sudah ada tidak ditimpa dengan data dari baris masuk, karena baris masuk tidak memiliki versi barisOriginal
.
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