DataRow'u kopyalamanın veya klonlamanın basit yolu?


118

DataRow'un bir klonunu yapmanın basit bir yolunu arıyorum. O Satırın anlık görüntüsünü alıp kaydetmek gibi. Orijinal Satır'ın değerleri daha sonra değiştirilebilir, ancak yine de değişmeyen başka bir kaydedilmiş kopyamız var. Bunu yapmanın doğru yolu bu mu?

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

Bu sadece Snapshot'ın ItemArray referansını Source'taki bir referansa mı ayarlayacak yoksa aslında ayrı bir kopya mı oluşturacak? Bunun yerine bunu yapmalı mıyım?

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

DÜZENLEME: İkinci kod parçacığının gerçekten derlendiğini sanmıyorum.


Anladığımdan emin değilim, bir datarow'u bir tablodan diğerine kopyalamak mı istiyorsunuz? Eğer öyleyse DataTable.ImportRow'un peşinde olduğunuzu düşünüyorum.
Mo Patel

Tamam, şimdi sorumun yeniden çalışması gerektiğini görüyorum
Paul Matthews

2
Bazı senaryolarda, datarow'un kendisi BeginEdit / EndEdit / CancelEdit ile işlemsel düzenlemeyi desteklediği için bunu yapmanız gerekmeyebileceğini unutmayın; ayrıca .RejectChanges çağırabilirsiniz.
peterG

Yanıtlar:


185

Row DataTable'dan DataTable'a aynı şema ile kopyalamak için ImportRowyöntemi kullanabilirsiniz :

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

Güncelleme:

Yeni Düzenlemenizle inanıyorum:

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

çalışacak


Görünüşe göre Clone () yalnızca yüzeysel bir kopya sağlar. Özdeş bir kopya oluşturmak için yeterli olacağını mı düşünüyorsunuz yoksa derin bir klon gerekli mi?
Paul Matthews

5
@PaulMatthews: Neyse ki DataTable, ref türü değil değer türleri içeriyor, bu nedenle değer türündeki sığ kopya derin kopya ile aynı
cuongle

16
Bu yazıyı bulan insanlar için, sık sık sorulduğu için aşağıdakileri ekleyeceğim, bu yüzden diğer insanların kafası karışmış olabilir. Klonla yalnızca yapıyı kopyalayın, Yapıyı kopyalayın sonra verileri kopyalayın. Her iki tablo da oluşturulduktan sonra verileri kopyalamanın başka bir kolay yolu, hedef tabloda yeni bir satır oluşturmak ve aşağıdakileri kullanmaktır: destRow.ItemArray = sourceRow.ItemArraysonra basitçedestTable.Rows.Add(destRow);
Franck

1
Bu yöntemi bir datarow klonu elde etmek için kullanmaya çalışıyorum. Adımları takip ediyorum, ardından kaynak satırı içeren datatable'ı temizliyorum ve şimdi boş alanları olan bir kaynak satırım var.
Sergеу Isupov

NewRow yönteminin işe yaramadığı yerde ImportRow yöntemini kullanmanın benim için işe yaradığını buldum.
OldDog

2

Not: cuongle'ın helfpul cevabı tüm bileşenlere sahiptir, ancak çözüm basitleştirilebilir (gerek yoktur .ItemArray) ve sorulduğu gibi soruyu daha iyi eşleştirmek için yeniden çerçevelendirilebilir.

Belirli bir System.Data.DataRowörneğin (izole edilmiş) klonunu oluşturmak için aşağıdakileri yapabilirsiniz:

// 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];

Not: Değer türü örnekleri olan sütun değerleriyle olduğu gibi çalışan sığ klonlama gerçekleştirilir , ancak referans türü örnekleri içeren sütun değerlerinin bağımsız kopyalarını oluşturmak için daha fazla çalışma yapılması gerekir (ve bu tür bağımsız kopyaların oluşturulması her zaman mümkün değildir. ).


1

Görünüşe göre tüm DataTable'ı bir kopya olarak tutmak istemiyorsunuz, çünkü sadece bazı satırlara ihtiyacınız var, değil mi? Tabloda bir seçim ile belirtebileceğiniz bir creteria varsa, yalnızca bu satırları DataRow'un ekstra bir yedek dizisine kopyalayabilirsiniz

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

.Select () işlevinin birkaç seçeneği vardır ve bu, örneğin bir SQL olarak okunabilir

SELECT * FROM sourceTable WHERE searchColumn = value;

Daha sonra yukarıda açıklandığı gibi istediğiniz satırları içe aktarabilirsiniz.

targetTable.ImportRows(rows[n])

... istediğiniz herhangi bir geçerli n için, ancak sütunların her tabloda aynı olması gerekir.

ImportRow hakkında bilmeniz gereken bazı şeyler, birincil anahtarları kullanırken çalışma sırasında hatalar olacağıdır!

Önce, eksik birincil anahtar nedeniyle başarısız olan bir satırın var olup olmadığını kontrol etmek istedim, ancak daha sonra kontrol her zaman başarısız oldu. Sonunda mevcut satırları tamamen temizlemeye ve istediğim satırları tekrar içe aktarmaya karar verdim.

İkinci sorun ne olduğunu anlamaya yardımcı oldu. İçe aktarma işlevini kullanma şeklim, satırları değiştirilmiş bir girişle bir sütunda çoğaltmaktır. Her zaman değiştiğini ve yine de dizideki satıra bir referans olduğunu fark ettim. Önce orijinali içe aktarmam ve sonra istediğim girişi değiştirmem gerekiyordu.

Referans ayrıca satırı gerçekten iki katına çıkardığı için ilk kez içe aktarmaya çalıştığımda ortaya çıkan birincil anahtar hatalarını da açıklıyor.


-4

Ancak yeni satırınızın yeni tabloda erişilebilir olduğundan emin olmak için tabloyu kapatmanız gerekir:

DataTable destination = new DataTable(source.TableName);
destination = source.Clone();
DataRow sourceRow = source.Rows[0];
destination.ImportRow(sourceRow);

3
İkinci kod satırı değişkeni yeniden atarsa, ilk kod satırının anlamı nedir?
Erik Philips

Bu cevap daha fazla açıklama kullanabilir (ve tabloyu kapatmamın ne anlama geldiğini bilmiyorum ) ve @ErikPhilips'in bir anlamı var ( DataTable destination = source.Clone()yapmalı), ancak aksi takdirde bu cevap mükemmel ve hatta .ItemArraykabul edilen cevaptaki yaklaşıma göre tercih edilebilir .
mklement0
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.