Как использовать мои собственные методы или написать функцию DbFunction для запросов EF Core (EF Core 3.0) - PullRequest
1 голос
/ 17 октября 2019

У меня ранее были следующие настройки:

public static bool BlogIsLive(BlogPost b)
{
    return b.Status == (int)ItemStatus.Active && b.PublishDate < DateTime.Now ;
}

/// Database query

var blogs = (from b in db.BlogPost 
             where BlogIsLive(b) // <--- super useful, used in multiple places
             select b
             ).ToList()

Но после обновления до EF Core 3.0 выдает следующую ошибку

/// The LINQ expression ... could not be translated. Either rewrite the query in a form 
/// that can be translated, or switch to client evaluation explicitly by inserting a 
/// call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync().

Я понимаю, что это часть взломаИзменения в EF Core 3.0

Теперь мне нужно написать запрос вручную во всех местах, где раньше был BlogsIsLive().

var blogs = from b in db.BlogPost 
            where b.Status == (int)ItemStatus.Active  //<--- Annoying repetition of code
            && b.PublishDate < DateTime.Now           //<---
            select b

Это очень раздражает. Нет ли способа, которым я могу написать метод, который вставляет туда?

Я знаю, что в EF есть DbFunctions, которые, например, могут упростить процесс сравнения Date значений, поэтому я не вижу причин, по которым было бы невозможно написать что-то свое, что делает подобное с участием Int, string или bool.

Что-то вроде:

public static DbFunction BlogIsLive(BlogPost b)
{
    //Example
    return DbFunction(b.Status == (int)ItemStatus.Active && b.PublishDate < DateTime.Now);
}

/// Database query

var blogs = (from b in db.BlogPost 
             where MyDbFunctions.BlogIsLive(b)
             select b
             ).ToList();

Я пробовал несколько вариантов выше, но не повезло.

Спасибо.

Ответы [ 2 ]

2 голосов
/ 17 октября 2019

В исходном коде есть серьезная ошибка, которая может привести к любой неосновной версии EF - это локальная функция, которую нельзя преобразовать в SQL. Where принимает выражения в качестве аргументов, а не функций. Вам не нужна эта функция в любом случае.

LINQ работает с IQueryable и выражениями. Каждый оператор берет один IQueryable и возвращает другой. Вот так Where и Select уже работают. Это означает, что вы можете создать свою собственную функцию, которая добавляет необходимое условие Where:

public static IQueryable<BlogPost> WhereActive(this IQueryable<BlogPost> query)
{
    return query.Where(b=>b.Status == (int)ItemStatus.Active && b.PublishDate < DateTime.Now);
}

и использовать его с любым IQueryable<BlogPost>, например:

var finalQuery = query.WhereActive();
var posts=finalQuery.ToList();

Другое, болеегромоздким вариантом является создание вызова Expression<Func<>> в коде и передача его в Where - по существу, создание условия WHERE динамически. В этом случае это не требуется.

EF Core 1.0 добавил очень неудачную функцию (больше похожую на what-were-they-thinking!), оценку на стороне клиента. Если что-то не может быть переведено, просто загрузите все в память и попробуйте отфильтровать содержимое без индексации, планов выполнения, алгоритмов сопоставления, ОЗУ и ЦП, найденных на сервере базы данных.

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

В веб-приложении это приводит к большему количеству серверов для обработкитот же трафик.

Вот почему оценка на стороне клиента была удалена , когда EF 1.0 была введена еще в 2008 году.

1 голос
/ 17 октября 2019

Вместо использования db.BlogPost в качестве базы запроса вы можете использовать DbSet, в котором уже есть этот фильтр.

DbSet<BlogPost> _allBlogs {get;set;}

IQueryable<BlogPost> ActiveBlogs { get => _allBlogs.Where(b=> b.Status == (int)ItemStatus.Active); }

var blogs = from b in db.ActiveBlogs
        select b
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...