-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Description
In the following query:
public virtual Task Inline_collection_Contains_with_all_parameters(bool async)
{
var (i, j) = (2, 999);
return AssertQuery(
async,
ss => ss.Set<PrimitiveCollectionsEntity>().Where(c => new[] { i, j }.Contains(c.Id)),
entryCount: 1);
}
ParameterExtractingEV client-evaluates the NewArrayExpression (since it contains no server-correlated data), and transforms the entire thing into a single parameter. This causes us to send the following SQL on SQL Server:
@__p_0='[2,999]' (Size = 4000)
SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE EXISTS (
SELECT 1
FROM OpenJson(@__p_0) AS [p0] -- Not good
WHERE CAST([p0].[value] AS int) = [p].[Id])
Ideally, this LINQ query would be translated to an IN expression with two parameters instead:
WHERE [p.Id] IN (@i, @j)
This would reproduce the constant array in the original LINQ query, and would give the database the opportunity to optimize for the fact that there are two parameters; it would very likely run faster than the generic OpenJson version, which has the same SQL regardless of the number of parameters.
The main problem here is the change to refrain client-evaluating the NewArrayExpression even though it contains no database-correlated things. Allowing arbitrary expressions in the inline expression (not just constants and parameters) is tracked by #30734.