如何使用LINQ查询找到两列之间的差异?

时间:2012-08-31 16:11:53

标签: c# linq

我有两个数据表,并希望连接这两个表来查找两列之间的差异,但是它会一直返回null并在CopyToDataTable方法中出错,因为您无法将null传递给它。我在此代码之前检查过TestOutput和ExpectedOutput表中的数据完全相同。 这是我的代码:

IEnumerable<DataRow> diff =
  (from datarows1 in TestOutput.AsEnumerable()
   join datarows2 in ExpectedOutput.AsEnumerable() 
   on datarows1.Field<String>("external_id") equals datarows2.Field<String>("external_id")

   select new
   {
      KeyId = datarows1.Field<String>("external_id"),
      Difference = datarows1.Field<Decimal>("quantity") - datarows2.Field<Decimal>("quantity")
    }) as IEnumerable<DataRow>;

DataTable difference = diff.CopyToDataTable<DataRow>();

错误消息@ last row:

  

ArgumentNullException未处理 - 值不能为null。参数名称:source

3 个答案:

答案 0 :(得分:2)

问题是as IEnumerable<DataRow>演员。如果删除该行,您会看到您的查询选择的是一个匿名类型,其中包含属性KeyIDDifference一个IEnumerable。 as运算符会尝试转换IEnumerable<DataRow>并返回null,如果没有这样的强制转换。这就是你的空引用异常来自的地方。

要解决此问题,您需要找到一种不同的方法来填充IEnumerable<a'>中的DataTable(其中a'是匿名类型)

DataTable difference = new DataTable();
difference.Columns.Add("KeyID", typeof(string));
difference.Columns.Add("Difference", typeof(decimal));

foreach (var result in diff)
   difference.Rows.Add(result.KeyID, result.Difference);

答案 1 :(得分:2)

问题是当你这样做时:

select new {...}

您正在创建一个匿名类,而不是DataRow。因此,当你施展as IEnumerable<DataRow>时,它变为null

如果使用隐式类型变量:

 var diff = 
  (from datarows1 in TestOutput.AsEnumerable() 
   join datarows2 in ExpectedOutput.AsEnumerable()  
   on datarows1.Field<String>("external_id") equals datarows2.Field<String>("external_id") 

   select new 
   { 
      KeyId = datarows1.Field<String>("external_id"), 
      Difference = datarows1.Field<Decimal>("quantity") - datarows2.Field<Decimal>("quantity") 
    }); 

这将创建正确类型的差异。

答案 2 :(得分:0)

您在select new中使用了匿名类型,而不是使用匿名类型,您应该使用某种继承自DataRow的类型,如当前的表类型:

.....
select new MyDataType
{
   external_id= datarows1.Field<String>("external_id"),
   quantity = datarows1.Field<Decimal>("quantity") 
              - datarows2.Field<Decimal>("quantity")
}) .ToList();

DataTable difference = diff.CopyToDataTable<DataRow>();

实际上你的演员表是无效的,它将被转换为null。