【问题标题】:How to merge two datatables with PrimaryKeys?如何将两个数据表与 PrimaryKeys 合并?
【发布时间】:2019-07-25 10:07:01
【问题描述】:

我有两个数据表,想要合并列并创建为第三个表。

//Given
dt1 {A(PK),B,C,D}
dt2 {a(PK),b,c,d}
//Want
dtResult {A,B,C,D,a,b,c,d}

不想丢失ExtendedProperties 所以不要选择DataColumn.ColumnName 并添加为列。

代码:

DataTable dt1 = new DataTable();
dt1.TableName = "dt1";
dt1.PrimaryKey = new DataColumn[] { dt1.Columns.Add("A") };
dt1.Columns.Add("B");
dt1.Columns.Add("C");
dt1.Columns.Add("D");

DataTable dt2 = new DataTable();
dt2.TableName = "dt2";
dt2.PrimaryKey = new DataColumn[] { dt2.Columns.Add("a") };
dt2.Columns.Add("b");
dt2.Columns.Add("c");
dt2.Columns.Add("d");

var dtResult = dt1.Clone();
dtResult.TableName = "dtResult";

到这里为止工作正常

现在要合并...

多次合并尝试类型 1

dtResult.Merge(dt2.Clone()); 
dtResult.Merge(dt2.Clone(), false);
dtResult.Merge(dt2.Clone(), true);
dtResult.Merge(dt2.Clone(), false, MissingSchemaAction.Add);
dtResult.Merge(dt2.Clone(), false, MissingSchemaAction.AddWithKey); 
dtResult.Merge(dt2.Clone(), true, MissingSchemaAction.Add);
dtResult.Merge(dt2.Clone(), true, MissingSchemaAction.AddWithKey);

在上述所有尝试中,列是 merged 到 dtResult 但抛出 NullReferenceException。 堆栈跟踪:

System.NullReferenceException
  HResult=0x80004003
  Message=Object reference not set to an instance of an object.
  Source=System.Data
  StackTrace:
   at System.Data.Merger.MergeSchema(DataTable table)
   at System.Data.Merger.MergeTableData(DataTable src)
   at System.Data.Merger.MergeTable(DataTable src)
   at System.Data.DataTable.Merge(DataTable table, Boolean preserveChanges, MissingSchemaAction missingSchemaAction)
   at Demo.Program.Test5() in C:\App\Demo\Program.cs:line 54
   at Demo.Program.Main(String[] args) in C:\App\Program.cs:line 36

多次合并尝试类型 2

dtResult.Merge(dt2.Clone(), false, MissingSchemaAction.Error);
dtResult.Merge(dt2.Clone(), true, MissingSchemaAction.Error);

在所有上述尝试中,列是 NOT merged 到 dtResult 和 System.Data.DataException 堆栈跟踪:

System.Data.DataException
  HResult=0x80131920
  Message=Target table  missing definition for column a.
  Source=System.Data
  StackTrace:
   at System.Data.Merger.MergeSchema(DataTable table)
   at System.Data.Merger.MergeTableData(DataTable src)
   at System.Data.Merger.MergeTable(DataTable src)
   at System.Data.DataTable.Merge(DataTable table, Boolean preserveChanges, MissingSchemaAction missingSchemaAction)
   at Demo.Program.Test5() in C:\App\Demo\Program.cs:line 54
   at Demo.Program.Main(String[] args) in C:\App\Demo\Program.cs:line 36

多次合并尝试类型 3

dtResult.Merge(dt2.Clone(), false, MissingSchemaAction.Ignore);
dtResult.Merge(dt2.Clone(), true, MissingSchemaAction.Ignore);

在上述所有尝试中,列是 NOT merged 到 dtResult 和 NO exception

【问题讨论】:

  • 预期结果是什么?
  • dtResult 应该包含所有列(A、B、C、D、a、b、c、d)。键列是可选的。

标签: c# .net datatable


【解决方案1】:

显然,发生 NullReferenceException 是因为这两个表具有主键。我们需要做一些事情来避免这种冲突。

你去吧:

var dtResult = dt1.Clone();
dtResult.TableName = "dtResult";

var dt2Cloned = dt2.Clone();
dt2Cloned.PrimaryKey = null;
dtResult.Merge(dt2Cloned);

var primaryKeys = dtResult.PrimaryKey.ToList();
foreach (var col in dt2.PrimaryKey)
{
    primaryKeys.Add(dtResult.Columns[col.ColumnName]);
}
dtResult.PrimaryKey = primaryKeys.ToArray();

这可能会进行一些优化,但它会为您提供所需的结果,因此这是一个良好的开始。

【讨论】:

  • 非常感谢@Ahmed Abdelhameed。制作PrimaryKey=null 并没有欺骗我,而是我试图删除该列。因为我不关心将密钥重新应用到新表中,所以 PrimaryKey=null 就足够了。再次感谢!
  • 好吧,我在一些博客上阅读了问题中也提到的原因,但不知何故我在编辑问题后删除了该行。但是不知道怎么解决。它现在可以工作了。
【解决方案2】:

除了@Ahmed Abdelhameed 的回答。

如果您遇到Unique column cannot have same valuenull is not allowed 之类的问题,请添加以下代码。

var dt2Cloned = dt2.Clone();
var pks = dt2Cloned.PrimaryKey.ToList();
dt2Cloned.PrimaryKey = null;
pks.ForEach(pk => { pk.Unique = false; pk.AllowDBNull = true; });

如果需要,您也可以对 dt1 中的 PKs 执行相同操作。

【讨论】:

    猜你喜欢
    • 2021-05-09
    • 2017-01-21
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-14
    相关资源
    最近更新 更多