在Entity Framework LINQ查询中使用IEnumerable.Contains时如何避免查询计划重新编译?

问题描述 投票:30回答:2

我使用Entity Framework(v6.1.1)执行以下LINQ查询:

private IList<Customer> GetFullCustomers(IEnumerable<int> customersIds)
{
    IQueryable<Customer> fullCustomerQuery = GetFullQuery();
    return fullCustomerQuery.Where(c => customersIds.Contains(c.Id)).ToList();
}

这个查询被翻译成相当不错的SQL:

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[FirstName] AS [FirstName]
-- ...
FROM [dbo].[Customer] AS [Extent1]
WHERE [Extent1].[Id] IN (1, 2, 3, 5)

但是,我在查询编译阶段获得了非常显着的性能影响。呼叫:

ELinqQueryState.GetExecutionPlan(MergeOption? forMergeOption) 

占用每个请求约50%的时间。深入研究,结果是每次我传递不同的customersIds时都会重新编译查询。根据MSDN article,这是一种预期的行为,因为在查询中使用的IEnumerable被认为是volatile,并且是缓存的SQL的一部分。这就是为什么SQL对于customersIds的每个不同组合都不同,它总是有不同的哈希值,用于从缓存中获取编译查询。

现在问题是:如何在仍然查询多个customersIds时避免重新编译?

performance linq entity-framework linq-to-entities
2个回答
© www.soinside.com 2019 - 2024. All rights reserved.