2015-10-24 1 views
0

Я в настоящее время реализую repository pattern для моего приложения ASP.VNext. Я хотел бы, чтобы методы были асинхронными и фильтруемыми. Таким образом, я разработал следующий метод интерфейса:Почему я не могу использовать ToListAsync() при использовании параметра для предиката в EF7?

Task<TEntity> GetOneAsync(Func<TEntity,bool> predicate);

и хотели бы реализовать это следующим образом (с частным DbContext например ctx):

public async Task<MyEntity> GetOneAsync(Func<MyEntity,bool> predicate) 
{ 
    // compiler error 
    return await ctx.MyEntities.Where(predicate).FirstOrDefaultAsync(); 
} 

Однако я могу использовать только FirstOrDefaultAsync() когда жестко прописывать предикат, как это:

return await ctx.MyEntites.Where(e => e.Id == 1).FirstOrDefaultAsync();

При переходе предиката я получаю только FirstOrDefault() без опции асинхронной, поэтому для того, чтобы сделать мой метод асинхронным я должен написать

public async Task<MyEntity> GetOneAsync(Func<MyEntity,bool> predicate) 
{ 
    //save to a local variable to prevent calling a disposed DbContext 
    var entities = await Task.Run(() => ctx.Contracts.Where(predicate).FirstOrDefault()); 
    return entities; 
} 

У меня есть два вопроса относительно этого:

  1. Почему невозможно получить доступ к методу FirstOrDefaultAsync() при передаче предиката?

  2. Выполняет ли мое решение с использованием await Task.Run(synchronousMethod) такое же поведение, как и вызов FirstOrDefaultAsync()?

+0

Что касается 1, можете ли вы отправить полный код и сообщение компилятора. Вероятно, тривиальная проблема. – usr

ответ

1

FirstOrDefaultAsync определяется как метод расширения для IQueryable<T>.

ctx.MyEntities.Where(e => e.Id == 1) возвращение IQueryable<MyEntity>.

ctx.MyEntities.Where(predicate) возвращается IEnumerable<MyEntity>, потому что вы вызываете метод Enumerable.Where расширения, а не Queryable.Where один.

Для того, чтобы это сработало, измените код predicate от Func<MyEntity, bool> до Expression<Func<MyEntity, bool>>. Это означает, что predicate больше не просто функция, которая дает нужный результат, а описание этой функции, которую Entity Framework может затем перевести на SQL.

И нет, используя Func<MyEntity, bool> в задаче не будет иметь такое же поведение. Это будет загружать строки с сервера db без какой-либо фильтрации и оценивать каждый клиент db до тех пор, пока не будет найдено совпадение. Это добавит много накладных расходов.

Смежные вопросы