2016-11-11 68 views
0

我有一个列表和两个表。 (这是实际的架构的一个非常简化的版本,但应为问题工作)Linq加入具有左外连接查询的查询未找到引用对象引用

List_A
FPI

表-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中没有值的条目失败。

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


我不知道为什么这个错误即将到来,这个问题最好的解决方案是什么?

+0

的可能的复制[什么是一个NullReferenceException,以及如何解决?(http://stackoverflow.com/问题/ 4660142/what-is-a-nullreferenceexception-how-do-i-fix-it) – mybirthname

+0

我也这样做过。我甚至尝试删除可能引发异常的参数。 –

回答

0

您的查询将是非常有效的,如果它是一个LINQ到实体查询转换为SQL。

然而,因为查询的根是List_A其不是IQueryable,整个查询执行LINQ到对象的上下文,其中,你应该执行对左外的右侧变量null检查加入任何地方,包括进一步加入条件。

所以,简单的解决将是使用

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

但是,请注意查询效率非常低。由于它解析为Enumerable方法,整个Table_BTable_C将在内存中读取,然后加入。

一个更好的方法是将数据库和内存中的查询分离:

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(); 
+0

感谢Ivan Stoev,工作。 –

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(); 
+0

此工作无异常,但返回Table_B中具有列FPI值的行。此查询的目的是获取左连接。 –