2016-08-25 113 views
0

我有三個表。
表Alinq連接查詢返回null

id name des   table2  table3 
1 xyz TableA_des1 null  1 
2 abc TableA_des2 1   2 
3 hgd TableA_des2 2   3 

表B

id name des   Active 
1 xyz TableB_des1 1 
2 abc TableB_des2 1 
3 hgd TableB_des2 1 

表C

id name des   Active 
1 xyz TableC_des1 1 
2 abc TableC_des2 1 
3 hgd TableC_des2 1 

LINQ查詢

var res = (from a in TableA 
       where id = 1 

       join b in TableB on a.table2 equals b.id into ab 
       from bdata in ab.DefaultIfEmpty() 
       where bdata.Active = true 

       join c in TableC on a.table3 equals c.id into ac 
       from cdata in ac.DefaultIfEmpty() 
       where cdata.Active = true 

       select new { data1 = a.name, data2 = bdata?? string.Empty, data3 = cdata?? string.Empty}) 

的有關查詢是給空。對調試變量res有空。

+1

不返回'null'但一個空的集合。 Linq查詢不返回'null'(除非你從中檢索到可能爲空的特定記錄) –

回答

3

您應該避免將where條件放在來自left outer join右側的範圍變量上,因爲這樣可以有效地將它們轉換爲inner join

相反,您應該前申請右側過濾聯接:

from a in TableA 
where id = 1 

join b in TableB.Where(x => a.Active) 
on a.table2 equals b.id 
into ab 
from bdata in ab.DefaultIfEmpty() 

join c in TableC.Where(x => x.Active) 
on a.table3 equals c.id 
into ac 
from cdata in ac.DefaultIfEmpty() 

... 

,或將它們聯接(如果可能):

from a in TableA 
where id = 1 

join b in TableB 
on new { id = a.table2, Active = true } equals new { b.id, b.Active } 
into ab 
from bdata in ab.DefaultIfEmpty() 

join c in TableC 
on new { id = a.table3, Active = true } equals new { c.id, c.Active } 
into ac 
from cdata in ac.DefaultIfEmpty() 

... 

爲了理解爲什麼是,當bdatanull(即沒有匹配的記錄)時,嘗試評估where bdata.Active == true。實際上,如果這是LINQ to Objects,上述條件將生成NullReferenceException。但是,LINQ to Entities可以處理那些不帶任何例外的情況,因爲數據庫自然支持查詢中的null值,這些列通常是不可空的。因此,上面的簡單計算結果爲false,因此將篩選結果記錄並有效地消除left outer join的影響,根據定義,應該返回左側記錄,而不管是否存在匹配的右側記錄。

這意味着,實際上有第三種方式操作(雖然前兩個選項是優選) - 包括明確null檢查:

from a in TableA 
where id = 1 

join b in TableB 
on a.table2 equals b.id 
into ab 
from bdata in ab.DefaultIfEmpty() 
where bdata == null || bdata.Active 

join c in TableC 
on a.table3 equals c.id 
into ac 
from cdata in ac.DefaultIfEmpty() 
where cdata == null || cdata.Active 

... 
+0

它的工作原理,可以詳細描述你的答案 – anand

+0

不是那麼明顯 - 當右邊沒有匹配的記錄時該連接,'bdata'爲'null',因此'where bdata.Active = true'的計算結果爲'false',並阻止查詢返回記錄。 –

+0

如果在linq中有10個左連接,則會出現執行問題 – anand