对于Linq的多连接和左连接,哪种方法更好?

时间:2017-07-07 09:17:20

标签: sql entity-framework 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 :(得分: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运算符,因此第一个是&#34;正式&#34;同意LINQ模式来实现这样的运算符。而LINQ to Objects肯定是要走的路,因为Enumerable.Join实现使用快速哈希查找来执行相关性O(n + m)时间复杂度,而from ... .Where(...).DefaultIfEmpty()基本上是SelectMany IQueryable<T>具有线性搜索操作,复杂度为O(m * n)。

对于IQueryable<T>实现,它实际上取决于查询提供程序。对于EF6提供程序,这两个构造都是等效的,并被转换为同一个SQL。对于EF Core - 嗯,目前它还处于开发阶段并且存在许多错误和问题,特别是对于左连接,因此很难给出一般建议。

因此,对于test.xml实现,请始终检查查询提供程序功能 - 支持与否,它们如何翻译/处理等(LINQ在这方面有点破碎)。

一般来说,我会说使用第一种模式。在LINQ to Objects中必不可少,并且希望任何好的查询提供程序都能识别它。

但是专门针对EF6,它只是一个品味问题 - 因为EF6足够智能识别并将它们翻译成同一个SQL,性能也是一样的。