2017-07-07 71 views
0

我有多個表,我想多加入和離開的的LINQ一起加入他們。我嘗試了兩種不同的方法來實現它,看起來他們都返回正確的結果。哪種方法更適合Linq的多重連接和左連接?

每種方法產生不同的SQL查詢。例如方法1也爲查詢結尾的某些鍵生成Order By

我的問題是: 哪種方法你建議嗎?爲什麼(性能& ...)

方法1:

from t1 in Table1 
    // Inner Join on a foreign key in tb1 
    join t2 in Table2 on t1.fkId1 equals t2.Id1 
    // Left Join 
    join t3 in Table3 on t1.fkId1 equals t3.Id1 into ServCons 
    from t3 in ServCons.DefaultIfEmpty() 
    // Left Join 
    join t4 in Table4 on t3.Id2 equals t4.Id2 into t4 
    select new{t1,t2,t3,t4} 

enter image description here

方法2:

from t1 in Table1 
    // Inner Join on a foreign key in tb1 
    from t2 in Table2 .Where(w=>t1.fkId1 == t2.Id1) 
    // Left Join 
    from t3 in Table3 .Where(w=>t1.fkId1 == w.Id1).DefaultIfEmpty() 
    // Left Join 
    from t4 in Table4 .Where(w=>t3.Id2 ==w.Id2).DefaultIfEmpty() 
    select new{t1,t2,t3,t4} 

enter image description here


更新:

我認爲這是明顯,性能是一個程序和程序員的一個重要問題。 更低的成本更快的結果也是我的目標。所以,當我提及不同的SQL查詢一個有關性能的問題顯然不夠,一個好的寫關於優點和他們的將被接受的答案利弊兩種方法之間的比較。

+1

更好?在哪方面? –

+0

我不認爲他們會返回相同的結果。第一個是_inner join_,但不是第二個_outer_ join?如果您還發布了生成的sql,它可能會有所幫助。 –

+0

這些看起來像不同的查詢。即使他們是相同的,只有你可以根據你的數據來判斷哪個更快。另外第二個查詢是混合Linq樣式,這可能會讓人困惑。 – DavidG

回答

3

首先,SQL的區別是因爲兩個查詢不等價。

在第一查詢:

join t4 in Table4 on t3.Id2 equals t4.Id2 into t4 

實際上是一個group join其產生不同的形狀在所述突出部(t4是集合)。

如果你把它轉換成left outer join LINQ模式:

join t4 in Table4 on t3.Id2 equals t4.Id2 into t4Group 
from t4 in t4Group.DefaultIfEmpty() 

生成的SQL將是同一個(取決於查詢提供)。

現在關於性能。由於LINQ沒有特殊的left outer join運營商,第一個是「正式」同意的LINQ模式來實現這樣的運營商。因爲Enumerable.Join實現使用基於快速哈希的查找來執行相關度O(n + m)的時間複雜度,而from ... .Where(...).DefaultIfEmpty()基本上是SelectMany,其具有O(m * n)的線性搜索操作,複雜。

對於IQueryable<T>的實現,它確實取決於查詢提供程序。對於EF6提供者,兩個構造都是等價的,並被轉換爲同一個SQL。對於EF Core來說 - 目前它仍處於開發階段,並且存在許多錯誤和問題,尤其是對於左連接,因此很難給出一般性建議。

因此,對於IQueryable<T>實現,總是檢查查詢提供程序的功能 - 什麼是支持與否,如何翻譯/處理等(LINQ在這方面有點不同)。

一般來說,我會說使用第一種模式。在LINQ to Objects中必不可少,希望能被任何好的查詢提供者所認可。

但專門針對EF6而言,這只是一種品味問題 - 由於EF6足夠聰明,可以識別並將它們轉換爲同一個SQL,因此性能也是一樣的。

+1

我喜歡你在答案中提供的細節。再次感謝你。 – RAM