Entity Framework 查询缺少 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 服务器感到困惑。
您需要确保SQL服务器每次根据参数maxRetryCount
的实际值重新编译计划。这在 EF 中并不容易,但可以使用自定义数据库拦截器将 option (recompile)
提示添加到您的查询中来完成。
在此处查看详细信息SimpleTalk Article
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);
请注意,此拦截是全局启用的,而不是针对上下文的特定实例,因此您可能希望再次禁用它,以免其他查询受到影响。
我有这个 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 服务器感到困惑。
您需要确保SQL服务器每次根据参数maxRetryCount
的实际值重新编译计划。这在 EF 中并不容易,但可以使用自定义数据库拦截器将 option (recompile)
提示添加到您的查询中来完成。
在此处查看详细信息SimpleTalk Article
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);
请注意,此拦截是全局启用的,而不是针对上下文的特定实例,因此您可能希望再次禁用它,以免其他查询受到影响。