[英]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.