Заметил что Linq в .net core 2.0 возвращает IEnumerable, вместо привычного IQueryable, работать с EF можно, но если в БД будет 2 миллиона записей и они выгрузятся в память будет - плохо. В решения только нашёл подключить: System.Linq.Queryable. Но это не помогает, так как я не нашёл способа выкосить старый Linq.
Полного кода метода нет, так что ответ наугад:
IQueryable<TEntity> = dbSet.Where(predicate);
Скорее всего predicate объявлен как
Func<TEntity, bool> predicate = ...
Дело в том, что метод Queryable.Where принимает не Func<TEntity, bool>, а Expression<Func<TEntity, bool>>.
А вот метод Enumerable.Where принимает просто Func<TEntity, bool>.
Func<TEntity, bool> - это просто делегат, который принимает TEntity и возвращает bool. Внутри делегата может быть любой метод с подходящей сигнатурой.
Если вы напишете
Func<TEntity, bool> predicate = e => e.Id > 5;
то компилятор просто создаст метод вида
bool someMethod(TEntity e)
{
return e.Id > 5;
}
Этот делегат можно вызывать, но вот залезть внутрь делегата, достать оттуда содержимое метода и как-то его превратить в SQL не получится. Поэтому делегата достаточно для Enumerable, но не для Queryable.
Expression<Func<TEntity, bool>> - это объект, а не метод.
Если вы напишете в коде
Expression<Func<TEntity, bool>> predicate = e => e.Id > 5;
то компилятор развернет это примерно в
Expression<Func<TEntity, bool>> predicate = Expression.Lambda(
Expression.MakeBinary(
ExpressionType.Equal,
Expression.PropertyAccess("e", "Id"),
Expresison.Const("5")....
и вот такое дерево объектов LINQ-провайдер легко может разобрать и превратить в соответствующий код SQL.
Обычно в коде для работы с LINQ используют лямбды. Лямбды компилируются или в анонимные методы, или в деревья выражений, в зависимости от контекста. При этом дерево выражений считается предпочтительным вариантом. Т.е. если вы напишете
dbSet.Where(e => e.Id == 5);
то компилятор предпочтет перегрузку с Expression и, соответственно, механизм IQueryable. Но т.к. вы явно задали тип предиката как Func - вы принудительно выбрали IEnumerable.
Поменяйте тип у predicate на Expression<> и все будет ок.
Если использовать фильтрацию по Where, она будет выполнена на серверной стороне, и ничего лишнего выгружено не будет.
using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Where(b => b.Url.Contains("dotnet"))
.ToList();
}
Этот код сгенерирует SQL с условием WHERE blogs.Url LIKE '%dotnet%' и выполнит его на стороне бд в момент перечисления массива. В приведённом коде это произойдёт в момент вызова .ToList();
Почитайте документацию
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости