我有多个表格,我想通过 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}
方法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}
更新
我认为很明显性能是程序和程序员的一个重要问题。 成本更低,结果更快也是我的目标。所以,当我提到关于不同的SQL查询并提出有关性能的问题时,很明显,通过撰写关于利弊的两种方法之间的良好比较将被接受答案
答案 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
运算符,因此第一个是"正式"同意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,性能也是一样的。