Description
I've started to inline queries more often to reduce round-trips to the server for fetching IDs that later are used in other queries.
This is partly due to the limitations of using .Contains()
on an int-array.
Instead I use something similar to the following (stupid) example, of course my real queries are different in terms of complexity. Still, this demonstrates the issue clearly.
var offerId = 1;
var inlineQuery = context.Offers.Where(o => o.Id == offerId);
var firstQuery = context.OfferActions.Where(oa => inlineQuery.Contains(oa.Offer) && oa.Action == OfferActions.Established);
var secondQuery = context.OfferActions.Where(oa => inlineQuery.Contains(oa.Offer) && oa.Action != OfferActions.Established);
var query = firstQuery.Concat(secondQuery);
await query.ToListAsync();
SELECT [o].[Id], [o].[Action], [o].[OfferId], [o].[TimeCreatedUtc]
FROM [OfferActions] AS [o]
INNER JOIN [Offers] AS [o0] ON [o].[OfferId] = [o0].[Id]
WHERE EXISTS (
SELECT 1
FROM [Offers] AS [o1]
WHERE ([o1].[Id] = @__offerId_0) AND ([o1].[Id] = [o0].[Id])) AND ([o].[Action] = 1)
UNION ALL
SELECT [o2].[Id], [o2].[Action], [o2].[OfferId], [o2].[TimeCreatedUtc]
FROM [OfferActions] AS [o2]
INNER JOIN [Offers] AS [o3] ON [o2].[OfferId] = [o3].[Id]
WHERE EXISTS (
SELECT 1
FROM [Offers] AS [o4]
WHERE ([o4].[Id] = @__offerId_1) AND ([o4].[Id] = [o3].[Id])) AND ([o2].[Action] <> 1)
As you can see in the above SQL output, I now have two parameters __offerId_0
and __offerId_1
even though I used the same local variable offerId
.
Is there any way to force EF Core to reuse the parameters so that I only get a single parameter __offerId
used in both subqueries?
In my real-world example, sometimes I end up with >10 parameters of the exact same value and I think this gives the SQL server a poor chance to optimize the query properly.
Include provider and version information
EF Core version: 5.0 rc2
Database provider: Microsoft.EntityFrameworkCore.SqlServer