无法将数据表列从一个数据表复制到另一个数据表

9

如何将一个数据表中的一列复制到一个新的数据表?当我尝试这样做时,出现错误“列 'XXX' 已经属于另一个数据表。”

dataColumn = datatable1.Columns[1];
datatable2 = new DataTable();
datatable2.Columns.Add(dataColumn);

感谢您的提前支持。

1
如果您发布代码或XML,请在文本编辑器中突出显示这些行,并单击编辑器工具栏上的“代码”按钮(101 010)以使其格式化和语法高亮! - marc_s
可能是重复的问题:如何将DataTable的DataColumn数据复制到另一个DataTable? - Paŭlo Ebermann
6个回答

11

您无法复制DataColumns。您需要在新数据表中创建一个与旧数据表的列具有相同数据类型的新DataColumn,然后需要运行一个FOR循环,将所有数据从旧数据表带入新数据表。

请参阅以下代码。这假设数据表具有完全相同的行数。

DataTable dt1 = new DataTable();
DataTable dt2 = new DataTable();
dt2.Columns.Add("ColumnA", dt1.Columns["ColumnA"].DataType);
for (int i = 0; i < dt1.Rows.Count; i++) { dt2.Rows[i]["ColumnA"] = dt1.Rows[i]["ColumnA"]; }

此外,如果要复制的数据是引用类型而不是值类型,则可能需要查看该类型是否有.Clone()方法,或者自己编写一个。只在FOR循环中执行'this = that'将不适用于引用类型。


@Lane 谢谢。但我认为这种方法会非常昂贵,因为我可能需要复制超过1列,而行数可能超过100万。 - Ananth
1
你可以在同一个循环中复制多列数据。这是唯一的方法。 - SLaks
同意。如果您要将一个数据表的列复制到另一个数据表中,这是唯一的方法。它可能没有你想象的那么昂贵。试试看吧。 - Lane
@SLaks和@Lane - 你们在说谎!;-) 你也可以使用DataRelation和计算的DataColumn来完成它。 - sheikhjabootie
@Xcaliburp:如果随后想要更改其中一个表中的值,则不行。而且,这需要一个共同的键。 - SLaks
@SLaks - 共同的关键点是正确的,但我正在尝试想出一个例子,在这个例子中,我想要从一个DataTable复制一列数据到另一个DataTable,并且没有进行某种类型的连接(例如将StatusID连接到StatusTable以获取StatusName)。我想不出一个例子。因此,虽然您的观点是正确的,但我认为它可能有点牵强附会。 - sheikhjabootie

4

您不能复制DataColumn。(DataColumn与其表非常紧密地耦合在一起)

相反,您可以添加一个具有相同名称和数据类型的新列。

您可能正在寻找DataTable.Clone(),它将创建整个表的结构副本。(具有相同的架构,但没有数据)


1

想法一下,你的DataTable是否都在同一个DataSet中?

如果是这样,你可以在两个表的列之间创建一个命名为DataRelation的关系(类似于外键)。

然后,你可以向表中添加一个计算列,它的Expression属性设置为“Child(RelationName).ColumnName”或“Parent(RelationName).ColumnName”,具体取决于关系的方向。

这将给你与复制列相同的效果,但我认为它只会惰性地评估它。所以也许它会给你你需要的东西。

这里有一个示例说明它的工作原理。该示例使用Sum聚合函数,但你只需要引用列名,它就会在你的DataTable中复制它。

myDataSet.Relations.Add(
    "Orders2OrderLines", 
    myDataSet.Tables["Orders"].Columns["OrderID"], 
    myDataSet.Tables["OrderLines"].Columns["OrderID"]);

ordersTable.Columns.Add("OrderTotal", typeof(decimal), "Sum(Child(Orders2OrderLines).ExtendedPrice)");

HTH


我相当确定它不会惰性评估。此外,列中的值将永久链接,这可能是他想要的,也可能不是。 - SLaks
@SLaks - 你对链接的观点是正确的 - 它可以根据你的需求而有利或不利。我认为它懒惰的原因是因为链接。我想象内部实际上只是一个绑定到原始表中数据的委托 - 所以并没有进行实际的复制。如果我错了,我很想知道,因为我从未测试过这个... - sheikhjabootie
谢谢,但我的 DataTables 都在同一个 DataSet 中。 - Ananth
@Ananth - 那是打错字了吗?还是你说你的表格都在同一个 DataSet 中。如果是的话,那么这个方法可以解决问题。如果不是,那么这对你来说不是一个解决方案。祝你好运。 - sheikhjabootie

0
问题是由于C#不能重复使用已创建的对象实例并在多个DataTable上使用它所引起的。为此,每次循环迭代都需要创建一个新的DataCollumn对象。
foreach (DataTable table in DATASET.Tables)
{
    DataColumn yourDataCollumn = new DataColumn("Name of DataCollumn", typeof(Your data type));
    // your logic here
}

希望它有所帮助...


0
我使用了下面的代码,主要使用LINQ合并两个表格,并仅在最后循环行。虽然不太美观,但确实有效。使用join可以避免上述一些假设。
DataTable tableOne = getTableOne();
DataTable tableTwo = getTableTwo();

var oneColumns = tableOne.Columns.Cast<DataColumn>()
                                 .Select(p => new Column(p.ColumnName, DataType))
                                 .ToArray();

var twoColumns = tableTwo.Columns.Cast<DataColumn>()
                                 .Select(p => new DataColumn(p.ColumnName, p.DataType))
                                 .ToArray();


var matches = (from a in tableOne.AsEnumerable()
               join b in tableTwo.AsEnumerable() on a["column_name"] equals b["column_name"]
               select a.ItemArray.Concat(b.ItemArray)).ToArray();


DataTable merged = new DataTable();
merged.Columns.AddRange(oneColumns);
merged.Columns.AddRange(twoColumns);

foreach (var m in matches) { merged.Rows.Add(m.ToArray()); }

我认为他们不想将一个表与另一个表合并,听起来他们只想从第一个表中种植一个只有一列的表。 - Jesse

-2

无需循环,参考此处,希望这能解决你的问题...

DataTable dt = new DataTable(); 
//fill the dt here 
DataTable dt2 = new DataTable(); 
string[] strCols = {"Column Name to copy"}; 
dt2 = dt.DefaultView.ToTable("newTableName", false, strCols);

在这个问题中,创建一个新的DataTable不是被要求的。 (此外,第二个构造函数调用是多余的。) - Paŭlo Ebermann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接