表现:.Join vs .Contains - Linq to Entities

时间:2016-11-17 09:09:50

标签: c# sql-server entity-framework lambda linq-to-entities

我正在使用Linq实体来查询数据库以获取int列表以供进一步处理。我有两种方法可以获得如下列表:

首先是:

List<int> lstBizIds = new List<int>() { 1, 2, 3, 4, 5 };
List<int> lstProjectIds = context.Projects.Where(x => lstBizIds.Contains(x.businessId)).Select(x => x.projectId).ToList();

第二是:

List<int> lstBizIds = new List<int>() { 1, 2, 3, 4, 5 };
List<int> lstProjectIds = context.Projects.Join(lstBizIds, p => p.businessId, u => u, (p, u) => p.projectId).ToList();

现在我的问题是上面哪种方法的性能更好?如果第一个列表,即lstBizIds的大小增加,它是否也会影响性能?如果性能降低,建议我采用其他实施方式。

4 个答案:

答案 0 :(得分:4)

你应该使用Contains,因为EF可以产生更有效的查询。

这将是SQL连接:

SELECT Id
FROM Projects
INNER JOIN (VALUES (1), (2), (3), (4), (5)) AS Data(Item) ON Projects.UserId = Data.Item

这将是SQL Contains:

SELECT Id
FROM Projects
WHERE UserId IN (1, 2, 3, 4, 5, 6)

INJOIN效率更高,因为DBMS可以停止查看IN的第一个匹配项; JOIN总是在第一场比赛结束后结束。

您可能还想检查哪些查询实际发送到数据库。你总是需要比较SQL,而不是LINQ代码(显然)。

答案 1 :(得分:1)

执行连接非常有效,因为Where条件实际上执行了所有表的笛卡尔积,然后过滤满足条件的行。这意味着为每个行组合(n1 * n2 * n3 * n4)

评估Where条件

Join运算符从第一个表中获取行,然后仅获取第二个表中具有匹配键的行,然后仅获取第三个表中具有匹配键的行,依此类推。其次,contains会以迭代的方式工作,使其比join

答案 2 :(得分:0)


我选择第一个,因为它不会增加计算机的内存 如果您使用两个数组来比较条件,请从第二个选择。

答案 3 :(得分:0)

我花了很长时间试图找到一个程序中出现堆栈溢出错误的原因,其中一些简单的LINQ查询访问了一个中等大小的数据库。

对于ICollection的

,一边是~10k元素,另一边是sql表,从“join”到“Contains”的单一更改修复了堆栈溢出错误。

似乎尽管有比较性能,但Contains是一个更安全的选择。