Cara sederhana untuk menyalin atau mengkloning DataRow?

118

Saya mencari cara sederhana untuk membuat tiruan dari DataRow. Seperti mengambil snapshot dari Row dan menyimpannya. Nilai Row asli kemudian bebas berubah tetapi kami masih memiliki salinan tersimpan lain yang tidak berubah. Apakah ini cara yang benar untuk melakukannya?

DataRow Source, Destination;
// Assume we create some columns and fill them with values
Destination.ItemArray = Source.ItemArray;

Apakah ini hanya akan mengatur referensi ItemArray Snapshot untuk menunjuk ke yang ada di Source atau apakah itu benar-benar membuat salinan terpisah? Haruskah saya melakukan ini?

Destination.ItemArray = Source.ItemArray.Clone();

EDIT: Saya tidak berpikir cuplikan kode kedua benar-benar mengkompilasi.

Paul Matthews
sumber
Saya tidak yakin saya mengerti, Anda ingin menyalin datarow dari satu tabel ke tabel lain? Jika demikian saya percaya menggunakan DataTable.ImportRow adalah apa yang Anda cari.
Mo Patel
Oke, saya melihat bahwa pertanyaan saya perlu dikerjakan kembali sekarang
Paul Matthews
2
Perhatikan bahwa dalam beberapa skenario Anda mungkin tidak perlu melakukan ini karena datarow itu sendiri mendukung pengeditan transaksional dengan BeginEdit / EndEdit / CancelEdit; Anda juga dapat memanggil .RejectChanges di atasnya.
peterG

Jawaban:

185

Anda dapat menggunakan ImportRowmetode untuk menyalin Row dari DataTable ke DataTable dengan skema yang sama:

var row = SourceTable.Rows[RowNum];
DestinationTable.ImportRow(row);

Memperbarui:

Dengan Edit baru Anda, saya yakin:

var desRow = dataTable.NewRow();
var sourceRow = dataTable.Rows[rowNum];
desRow.ItemArray = sourceRow.ItemArray.Clone() as object[];

akan bekerja

cuongle
sumber
Rupanya Clone () hanya menyediakan salinan dangkal. Apakah menurut Anda itu cukup untuk membuat salinan yang identik atau diperlukan klon yang dalam?
Paul Matthews
5
@PaulMatthews: Untungnya DataTable berisi tipe nilai, bukan tipe ref, jadi salinan dangkal dalam tipe nilai os sama dengan salinan dalam
cuongle
16
Untuk orang-orang yang menemukan posting ini, saya akan menambahkan yang berikut ini karena saya sering ditanya sehingga saya rasa orang lain mungkin bingung. Klon salin struktur saja, Salin salin struktur lalu datanya. Cara lain yang mudah untuk menyalin data setelah kedua tabel dibuat adalah dengan membuat baris baru di tabel tujuan dan menggunakan yang berikut ini: destRow.ItemArray = sourceRow.ItemArraylalu tambahkan baris kembali dengan sederhanadestTable.Rows.Add(destRow);
Franck
1
Saya mencoba menggunakan metode ini untuk mendapatkan tiruan dari datarow. Saya melakukan langkah-langkah berikut, lalu saya menghapus datatable yang berisi baris sumber dan sekarang saya memiliki baris sumber dengan bidang kosong.
Sergеу Isupov
Saya menemukan bahwa menggunakan metode ImportRow berhasil untuk saya, sedangkan metode NewRow tidak.
OldDog
2

Catatan: jawaban helfpul cuongle memiliki semua bahan, tetapi solusinya dapat disederhanakan (tidak perlu .ItemArray) dan dapat disusun ulang agar lebih cocok dengan pertanyaan seperti yang ditanyakan.

Untuk membuat klon (terisolasi) dari System.Data.DataRowinstance tertentu , Anda dapat melakukan hal berikut:

// Assume that variable `table` contains the source data table.

// Create an auxiliary, empty, column-structure-only clone of the source data table.
var tableAux = table.Clone();
// Note: .Copy(), by contrast, would clone the data rows also.

// Select the data row to clone, e.g. the 2nd one:
var row = table.Rows[1];

// Import the data row of interest into the aux. table.
// This creates a *shallow clone* of it.
// Note: If you'll be *reusing* the aux. table for single-row cloning later, call
//       tableAux.Clear() first.
tableAux.ImportRow(row);

// Extract the cloned row from the aux. table:
var rowClone = tableAux.Rows[0];

Catatan: Kloning dangkal dilakukan , yang berfungsi sebagaimana adanya dengan nilai kolom yang merupakan contoh tipe nilai , tetapi lebih banyak pekerjaan akan diperlukan untuk juga membuat salinan independen dari nilai kolom yang berisi contoh tipe referensi (dan membuat salinan independen seperti itu tidak selalu memungkinkan ).

mklement0
sumber
1

Sepertinya Anda tidak ingin menyimpan seluruh DataTable sebagai salinan, karena Anda hanya memerlukan beberapa baris, bukan? Jika Anda memiliki kriteria yang dapat Anda tentukan dengan memilih di tabel, Anda dapat menyalin hanya baris tersebut ke array cadangan tambahan DataRow seperti

DataRow[] rows = sourceTable.Select("searchColumn = value");

Fungsi .Select () memiliki beberapa opsi dan yang ini misalnya dapat dibaca sebagai SQL

SELECT * FROM sourceTable WHERE searchColumn = value;

Kemudian Anda dapat mengimpor baris yang Anda inginkan seperti dijelaskan di atas.

targetTable.ImportRows(rows[n])

... untuk setiap valid yang Anda suka, tetapi kolomnya harus sama di setiap tabel.

Beberapa hal yang harus Anda ketahui tentang ImportRow adalah bahwa akan ada kesalahan selama runtime saat menggunakan kunci utama!

Pertama saya ingin memeriksa apakah baris sudah ada yang juga gagal karena kunci utama hilang, tetapi kemudian pemeriksaan selalu gagal. Pada akhirnya saya memutuskan untuk menghapus baris yang ada sepenuhnya dan mengimpor baris yang saya inginkan lagi.

Masalah kedua memang membantu untuk memahami apa yang terjadi. Cara saya menggunakan fungsi impor adalah menduplikasi baris dengan entri yang dipertukarkan dalam satu kolom. Saya menyadari bahwa itu selalu berubah dan itu masih merupakan referensi ke baris dalam larik. Saya pertama-tama harus mengimpor yang asli dan kemudian mengubah entri yang saya inginkan.

Referensi tersebut juga menjelaskan kesalahan kunci utama yang muncul ketika saya pertama kali mencoba mengimpor baris karena baris itu benar-benar digandakan.

Bolle
sumber
-4

Namun untuk memastikan bahwa baris baru Anda dapat diakses di tabel baru, Anda perlu menutup tabel:

DataTable destination = new DataTable(source.TableName);
destination = source.Clone();
DataRow sourceRow = source.Rows[0];
destination.ImportRow(sourceRow);
rdjabarov.dll
sumber
3
Apa poin dari baris pertama kode jika baris kedua kode menetapkan kembali variabel?
Erik Philips
Jawaban ini dapat menggunakan lebih banyak penjelasan (dan saya tidak tahu apa artinya perlu menutup tabel ) dan @ErikPhilips ada benarnya ( DataTable destination = source.Clone()harus dilakukan), tetapi jika tidak, jawaban ini baik-baik saja dan bahkan lebih disukai daripada .ItemArraypendekatan dalam jawaban yang diterima.
mklement0