繁体   English   中英

实体框架查询缺少SQL Server 2012上的筛选索引

[英]Entity Framework query missing a filtered index on SQL Server 2012

我有这个EF查询:(仅保留了关键部分)

int maxRetryCount = 5;
var erroredArchiveFilesQuery =
  transitionLogSessionContext.Set<ArchivedFile>().Where(f => 
  f.RetryCount < maxRetryCount
).Take(maxBatchSize);

它错过了可用的过滤索引。

而当像这样删除变量maxRetryCount

var erroredArchiveFilesQuery =
transitionLogSessionContext.Set<ArchivedFile>().Where(f => 
f.RetryCount < 5 && 
).Take(maxBatchSize);

将使用过滤后的索引。

来自第一个EF查询的实际SQL ...

SELECT TOP (500) 
    [Extent1].[Id] AS [Id], 
     ..
FROM  
    [ArchivedFile] AS [Extent1]
WHERE 
    ([Extent1].[RetryCount] < @p__linq__0 ) 

过滤后的索引包含列RetryCount和过滤器'RetryCount <5'

我如何用一个可以过滤索引的变量进行ef查询?

我认为问题出在准备的EF语句中,因此可以重新使用它,这使SQL Server感到困惑。

您需要确保SQL Server每次根据参数maxRetryCount的实际值重新编译计划。 这在EF中并不容易,但是可以使用自定义数据库拦截器向您的查询添加option (recompile)提示来完成。

在此处查看详细信息SimpleTalk文章

public class RecompileDbCommandInterceptor : IDbCommandInterceptor
{
    public void ReaderExecuting(DbCommand command,  DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
        if(!command.CommandText.EndsWith(" option(recompile)"))
        {
            command.CommandText +=  " option(recompile)";
        }
    }
}

您可以像这样使用它:

var interceptor = new RecompileDbCommandInterceptor();
DbInterception.Add(interceptor);

int maxRetryCount = 5;
var erroredArchiveFilesQuery =
  transitionLogSessionContext.Set<ArchivedFile>().Where(f => 
  f.RetryCount < maxRetryCount
).Take(maxBatchSize);

DbInterception.Remove(interceptor);

请注意,此拦截是全局启用的,而不是针对上下文的特定实例启用的,因此您可能希望再次禁用它,以使其他查询不受影响。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM