Reputation: 9052
So I've been digging in queries EF produces for our app and I noticed some strange sql generation of Any
calls - they seem to be overly complicated. Any
seem to generate case when (x) then 1 when (not x) then 0 end
- why not just use else? This way SQL server has to execute the same query twice in cases where Any
should return false
. I came up with workaround that seem to be faster in those cases using Where(cond).Select(q => true).FirstOrDefault()
, but I'm still interested in whether this is just oversight or it has some meaning I'm missing.
context.Books.Any(b => b.Id == bookId);
declare @p__linq__0 Int = 1;
SELECT
CASE WHEN ( EXISTS (SELECT
1 AS [C1]
FROM [Books] AS [Extent1]
WHERE [Extent1].[ID] = @p__linq__0
)) THEN cast(1 as bit) WHEN ( NOT EXISTS (SELECT
1 AS [C1]
FROM [Books] AS [Extent2]
WHERE [Extent2].[ID] = @p__linq__0
)) THEN cast(0 as bit) END AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
context.Books.Where(b => b.ID == bookId).Select(b => true).FirstOrDefault();
declare @p__linq__0 Int = 1;
SELECT TOP (1)
cast(1 as bit) AS [C1]
FROM [Books] AS [Extent1]
WHERE [Extent1].[ID] = @p__linq__0
Upvotes: 2
Views: 2570
Reputation: 11813
After you have seen that something does not exists it is pretty clear that it does indeed not exists, so checking agin if is really does not exist is not necessary. This is just one of those cases where linq is producing overly complicated queries. Your workaround works, but it is not necessarily as easy to understand as one would like, so I suggest to take the performance hit of the original linq until it really becomes a performance problem. Just make sure there is an index on the Id column.
Upvotes: 1