Linq连接查询与左外连接抛出对象引用未找到

时间:2016-11-11 06:54:42

标签: c# entity-framework linq left-join

我有一个列表和两个表。 (这是实际模式的一个非常简化的版本,但应该适用于该问题)

List_A
FPI
1
2
3
4个

表-B
FPI_______NI
2_________1
4_________2

Table_C
NI_______Name
1_________x
2_________y

我的linq查询:

(from a in List_A
 join b in Table_B on a.FPI equals b.FPI into ab
 from b in ab.DefaultIfEmpty()
 join c in Table_C on b.FI equals c.FI into bc
 from c in bc.DefaultIfEmpty()
 select new {
   FPI = a.FPI,
   Name = c?.Name}).ToList();

此代码抛出Object reference not set to an instance of an object.的异常。 经过大量的试验和实验,我得出的结论是,在第二次加入时我正在进行b.FI equals c.FI,那时对于Table_B中没有值的条目失败了。< BR />

查询的预期输出应为
ABC FPI____NI___Name
1_____null__null
2_____1_____x
3_____null__null
4_____2_____y


我不确定为什么会出现这个错误以及这个问题的最佳解决方案。

2 个答案:

答案 0 :(得分:0)

你可以尝试

 var list=(from a in Table_A
                join b in Table_B on a.FPI equals b.FPI into ab
                from b in ab.ToList()
                join c in Table_C on b.NI equals c.NI into bc
                from c in bc.DefaultIfEmpty()
                select new {
                FPI = a.FPI,
                Name = c.Name}).ToList();

<强>更新

         var list = (from a in Table_A
                     join b in Table_B on a.FPI equals b.FPI into ab
                     from b in ab.DefaultIfEmpty()
                     join c in Table_C on b == null ? 0 : b.NI equals c.NI into bc
                     from c in bc.DefaultIfEmpty()
                     select new
                     {
                         FBI = a.FPI,
                         NI = c != null ? c.NI : null,//if NI is nullable
                         //NI = c != null ? c.NI : 0,//if NI is not nullable
                         Name = c!=null?c.Name:null

                     }).ToList();

答案 1 :(得分:0)

如果将LINQ to Entities查询转换为SQL,您的查询将完全有效。

但是,由于查询的根目录List_A不是IQueryable,因此整个查询在LINQ to Objects上下文中执行,您应该在其中执行null检查左外连接的右侧变量,包括进一步的连接条件。

所以简单的解决方法就是使用

join c in Table_C on b?.FI equals c.FI into bc

但请注意,查询效率极低。由于已经解析为Enumerable方法,因此整个Table_BTable_C将在内存中读取,然后加入。

更好的方法是将db和内存查询分开:

var dbQuery =
    from b in Table_B
    join c in Table_C on b.FI equals c.FI into bc
    from c in bc.DefaultIfEmpty()
    select new { b.FPI, c.Name };

var query =
    from a in List_A
    join bc in dbQuery on a.FPI equals bc.FPI into abc
    from bc in abc.DefaultIfEmpty()
    select new
    {
       FPI = a.FPI,
       Name = bc?.Name
    };

var result = query.ToList();