2017-04-20 76 views
1

我有3个DataTable对象与我想加入的关系数据。 第一个有模式,看起来像如何使用Linq加入多个包含DBNull值的列上的多个DataTable

DataTable parent = new DataTable(); 
parent.Columns.Add("Id1", typeof(string)); 
parent.Columns.Add("Id2", typeof(string)); 
// more metadata 

无论在哪里的ID可能是DBNull的,但不能同时使用。

两个chlid表具有相同的模式。

DataTable child = new DataTable(); 
child.Columns.Add("Id1", typeof(string)); 
child.Columns.Add("Id2", typeof(string)); 
child.Columns.Add("BeginDate", typeof(DateTime)); 
child.Columns.Add("SomeData", typeof(float)); 
// more data 

我有一个函数,它将所有三个DataTables作为输入,并且应该返回连接的表。

var dataToReturn = // will be converted to a DataTable later. 
    from 
     p in parent.AsEnumerable() 
    join c1 in child1.AsEnumerable() 
     on new { 
      Id1 = p["Id1"], 
      Id2 = p["Id2"], 
     } 
     equals new { 
      Id1 = c1["Id1"], 
      Id2 = c1["Id2"], 
     } 
    join c2 in child2.AsEnumerable() 
     on new { 
      Id1 = p["Id1"], 
      Id2 = p["Id2"], 
      BeginDate = c1["BeginDate"], 
     } 
     equals new { 
      Id1 = p["Id1"], 
      Id2 = p["Id2"], 
      BeginDate = c1["BeginDate"], 
     } 
    select new { 
     Id1 = p["Id1"], 
     Id2 = p["Id2"], 
     BeginDate = c1["BeginDate"], 
     Child1Data = c1["SomeData"], 
     Child2Data = c2["SomeData"], 
    } 

然而,这不返回任何结果,即使有这些条件匹配的许多非空值。

如果我在写SQL(用“是不是区别于”从Postgres的使空= NULL为简洁返回true),我会写

select 
    p.Id1, 
    p.Id2, 
    c1.BeginDate, 
    c1.SomeData as Child1Data, 
    c2.SomeData as Child2Data 
from 
    Parent p 
    join Child1 c1 
     on c1.Id1 is not distinct from p.Id1 
     and c1.Id2 is not distinct from p.Id2 
    join Child2 c2 
     on c2.Id1 is not distinct from p.Id1 
     and c2.Id2 is not distinct from p.Id2 
     and c2.BeginDate = c1.BeginDate 

注意使用“是不是区别于”因为我想让“DBNull.Value == DBNull.Value”返回true,所以在ID字段中输入“=”。

我的问题:

是这可能跟内存的DataTable的LINQ? Linq如何在这些查询中处理DBNull.Value比较?

+0

为了回报一些东西,LINQ查询必须编译(张贴的没有) 。除此之外,它应该工作。如果没有,请发布[mcve]。 –

回答

0

Linq将正确匹配DBNull.Value到另一个DBNull.Value。我相信这是你的问题,而不是加入一个第二子表,因为这是微不足道的

DataTable parent = new DataTable(); 
parent.Columns.Add("Id1", typeof(string)); 
parent.Columns.Add("Id2", typeof(string)); 
DataRow r1 = parent.NewRow(); 
r1["Id1"] = "1"; 
r1["Id2"] = DBNull.Value; 
parent.Rows.Add(r1); 
DataRow r3 = parent.NewRow(); 
r3["Id1"] = "1"; 
r3["Id2"] = "2"; 
parent.Rows.Add(r3); 

DataTable child1 = new DataTable(); 
child1.Columns.Add("Id1", typeof(string)); 
child1.Columns.Add("Id2", typeof(string)); 
child1.Columns.Add("BeginDate", typeof(DateTime)); 
child1.Columns.Add("SomeData", typeof(float)); 
DataRow r2 = child1.NewRow(); 
r2["Id1"] = "1"; 
r2["Id2"] = DBNull.Value; 
child1.Rows.Add(r2); 
DataRow r4 = child1.NewRow(); 
r4["Id1"] = "1"; 
r4["Id2"] = "2"; 
child1.Rows.Add(r4); 

var dataToReturn = 
    from 
    p in parent.AsEnumerable() 
    join c1 in child1.AsEnumerable() 
    on new { Id1 = p["Id1"], Id2 = p["Id2"] } 
    equals new { Id1 = c1["Id1"], Id2 = c1["Id2"] } 
    select new 
    { 
     Id1 = p["Id1"], 
     Id2 = p["Id2"] 
    }; 

foreach(var l in dataToReturn) 
{ 
    Console.WriteLine(l.Id1 + "|" + l.Id2); 
} 

Console.ReadKey(); 

输出:

1| 
1|2 
+1

你是对的。在DBNull.Value上匹配默认工作。 @Ivan Stoev也是正确的,因为我发布的代码应该可以工作。我终于找到了问题。子表源是CSV,父母的JSON。其中一个用于JSON文件的Id用双引号括起来。我将CSV转换为DataTable的方法删除了引号,但JSON解串器没有。 Id!=“Id”。谢谢您的帮助! – user1858704