0

У меня есть этот EF запрос: (только сохранил основную часть)Entity Framework запрос отсутствует отфильтрованный индекс на SQL Server 2012

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); 

будет использовать фильтрованную индекс.

Действительное SQL с первого запроса EF ...

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

Отфильтрованный индекс содержит столбец RetryCount и фильтр «RetryCount < 5»

Как я могу сделать запрос эф с переменная, которая попадет в отфильтрованный индекс?

Я предполагаю, что проблема заключается в подготовке EF, поэтому его можно использовать повторно, и это смущает SQL Server.

+0

вы должны уточнить свой код. Ваш код недействителен (не компилируется). Также убедитесь, что вы пометили все разделы кода как код. – Mat

+0

У меня были проблемы с получением кода среднего кода, показанного как код, но переписывание его помогло. Я не собирался компилировать код, но, надеюсь, все основные части есть. Если проблема не имеет смысла сейчас, просто дайте мне знать, где я должен очистить. Спасибо –

+0

. Где (f => f.RetryCount <5 &&) Что должен делать этот кусок кода? – Mat

ответ

0

Необходимо, чтобы SQL Server перекомпилировал план каждый раз, основываясь на фактическом значении параметра 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); 

Обратите внимание, что этот перехват включен глобально, а не для конкретного экземпляра контекста, так что вы, вероятно, хотите чтобы отключить его снова, чтобы другие запросы не были затронуты.