复制或克隆DataRow的简单方法?


118

我正在寻找一种简单的方法来克隆DataRow。有点像为该行拍摄快照并将其保存。然后可以自由更改原始Row的值,但我们还有另一个已保存的副本,该副本不变。这是正确的方法吗?

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

这是否只是将Snapshot的ItemArray引用设置为指向Source中的那个,还是实际上是单独制作一个副本?我应该这样做吗?

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

编辑:我不认为第二个代码片段实际上可以编译。


我不确定我是否理解,您要将数据行从一个表复制到另一表?如果是这样,我相信使用DataTable.ImportRow是您所追求的。
Mo Patel 2012年

好吧,我看到我的问题现在需要重新处理
Paul Matthews

2
请注意,在某些情况下,您可能不需要这样做,因为数据行本身支持使用BeginEdit / EndEdit / CancelEdit进行事务性编辑。您也可以在其上调用.RejectChanges。
彼得

Answers:


185

您可以使用ImportRow方法将具有相同架构的Row从DataTable复制到DataTable:

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

更新:

通过您的新Edit,我相信:

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

将工作


显然,Clone()仅提供浅表副本。您是否认为足以创建相同的副本,还是需要深度克隆?
保罗·马修斯

5
@PaulMatthews:幸运的是,DataTable包含值类型,而不是引用类型,因此值类型os中的浅表副本与深表副本相同
cuongle 2012年

16
对于发现此帖子的人,我会在经常被问到的地方添加以下内容,因此我想其他人可能会感到困惑。仅克隆复制结构,然后复制复制结构,然后复制数据。就是说,一旦两个表都实例化后,复制数据的另一种简便方法是在目标表中创建新行并使用以下命令:destRow.ItemArray = sourceRow.ItemArray然后用destTable.Rows.Add(destRow);
Franck

1
我正在尝试使用此方法来获取数据行的克隆。我按照以下步骤进行操作,然后清除包含源行的数据表,现在有一个包含空白字段的源行。
Sergеу伊苏波夫

我发现使用ImportRow方法对我有用,而NewRow方法则不行。
OldDog

2

注意:cuongle的helfpul答案具有所有要素,但是可以简化解决方案(无需.ItemArray),并且可以重新设计框架以更好地匹配所提出的问题。

要创建给定System.Data.DataRow实例的(隔离)克隆,您可以执行以下操作:

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

注意:执行了克隆,它与作为值类型实例的列值一样按原样工作,但是还需要做更多的工作来创建包含引用类型实例的列值的独立副本(而且不一定总是可以创建这样的独立副本) )。


1

似乎您不想将整个DataTable保留为副本,因为您只需要一些行,对吗?如果您有一个条件,可以在表上进行选择,则可以仅将这些行复制到DataRow的额外备份数组中,例如

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

.Select()函数有几个选项,例如,可以将其读取为SQL

SELECT * FROM sourceTable WHERE searchColumn = value;

然后,您可以如上所述导入所需的行。

targetTable.ImportRows(rows[n])

...对于您喜欢的任何有效n,但每个表中的列都必须相同。

您应该了解有关ImportRow的一些信息,即使用主键在运行时会出错!

首先,我想检查是否存在由于缺少主键而导致行失败的行,但是随后检查始终失败。最后,我决定完全清除现有行,然后再次导入我想要的行。

第二个问题确实有助于了解发生了什么。我使用导入功能的方式是在一个列中复制带有交换条目的行。我意识到它总是在变化,仍然是对数组中行的引用。我首先必须导入原始文件,然后更改我想要的条目。

该参考资料还解释了我第一次尝试导入行时出现的主键错误,因为它实际上已经加倍了。


-4

但是,要确保新表中的新行可访问,您需要关闭表:

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

3
如果第二行代码重新分配了变量,那么第一行代码的意义是什么?
Erik Philips

这个答案可以使用更多的解释(我不知道关闭表的含义是什么),@ ErikPhilips有一个要点(DataTable destination = source.Clone()应该做),但是否则,这个答案非常好,甚至比.ItemArray公认答案中的方法更好。
mklement0
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.