2017-07-07 35 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