比较Entity Framework 5中Any()与Count()的生成查询的性能

在我的项目中,我使用Entity Framework 4.4.0.0,我遇到了以下两难困境。 我必须检查用户是否被激活。 我的查询看起来像:

任何()

_context.Users.Any(u => u.Id == userId && u.IsActivated); 

生成的sql是:

 SELECT CASE WHEN ( EXISTS (SELECT 1 AS [C1] FROM [dbo].[Users] AS [Extent1] WHERE ( [Extent1].[Id] = @p__linq__0 ) AND ( [Extent1].[IsActivated] = 1 )) ) THEN cast(1 AS BIT) WHEN ( NOT EXISTS (SELECT 1 AS [C1] FROM [dbo].[Users] AS [Extent2] WHERE ( [Extent2].[Id] = @p__linq__0 ) AND ( [Extent2].[IsActivated] = 1 )) ) THEN cast(0 AS BIT) END AS [C1] FROM (SELECT 1 AS X) AS [SingleRowTable1] 

对于Count()我得到这个查询:

 SELECT [GroupBy1].[A1] AS [C1] FROM (SELECT COUNT(1) AS [A1] FROM [dbo].[Users] AS [Extent1] WHERE ( [Extent1].[Id] = @p__linq__0 ) AND ( [Extent1].[IsActivated] = 1 )) AS [GroupBy1] 

这看起来不错吗? 我不是很好sql …但它对我来说效率不高。 我错过了什么吗?

select count(*) from dbo.Users where id=@id and IsActivated=1 ‘效率较低?

这取决于。

EXISTS实现也不是很好。 如果有0行,它将执行两次检查。 在这种情况下, COUNT将更好,因为它只需要搜索不存在的行并计算一次。

你可能会发现检查

 _context.Users .Where(u => u.Id == userId && u.IsActivated) .Select(u=> true) .FirstOrDefault(); 

给出了比两者更好的计划(根据卢克的建议修改)。 在EF4上测试生成的查询是沿着的

 SELECT TOP (1) cast(1 AS BIT) AS [C1] FROM Users WHERE userId = @userId AND IsActivated = 1 

这意味着如果存在多个行,则它不会处理不必要的额外行,并且只执行与WHERE匹配的行的搜索。

是的。 执行计数时,您将选择与您的子句匹配的所有条目,然后计数。 使用Any(),您的查询将返回与该子句匹配的注册表的第一个符号。 我是我的选择使用Any()而不是count()总是更好,除非你真的需要那个数字