Запрос пользовательского расширения EF Core, выражение LINQ не удалось перевести

#c# #asp.net #entity-framework #entity-framework-core

Вопрос:

как я могу сделать что-то подобное?

 public static class CustomExtensions
{
    public static IQueryable<TEntity> CustomWhere<TEntity>(this
            IQueryable<TEntity> entities,
        Expression<Func<TEntity, bool>> getProperty,
        bool isTrue)
    {
        return isTrue ? entities : entities.Where(getProperty);
    }
}


var users = (
from user in _context.Users

let userChange = _context.UsersChange.CustomWhere(e => e.RegisterName == request.RegisterName,
string.IsNullOrEmpty(request.RegisterName)).FirstOrDefault()

select new
{
    test = userChange
}).FirstOrDefault();
 

теперь у меня ошибка «Выражение LINQ не удалось перевести. Либо перепишите запрос в форму, которую можно перевести, либо переключитесь на клиентскую оценку EF Core 3.1»

Комментарии:

1. Немного неясно, о чем вы спрашиваете. Эта ошибка возникает из-за того, что выражение, которое вы пытаетесь использовать, не может быть использовано, поскольку нет способа перевести его в команду базы данных для прямого запуска. Вот почему он говорит вам переключиться на оценку клиентов. Если вы прогуглите свою ошибку, то получите множество результатов по этой проблеме. Если вы посмотрите на них и примените то же самое к своей проблеме, возможно, вам удастся обойти проблему. Также полезно создать минимальный проверяемый пример для публикации на SO — это может помочь вам понять, в чем проблема.

Ответ №1:

Пользовательские методы расширения можно использовать только с запросами верхнего уровня, так как это единственный случай, когда они фактически выполняются. При использовании внутри дерева выражений запроса (как в вашем примере) «вызов» просто записывается, но никогда не вызывается, и во время перевода они обрабатываются как любой неизвестный метод.

Следовательно, решение состоит в том, чтобы переместить вызов (конечно, когда это возможно) в переменную запроса верхнего уровня, а затем использовать переменную внутри фактического запроса, например

 var userChanges = _context.UsersChange
    .CustomWhere(e => e.RegisterName == request.RegisterName,
        string.IsNullOrEmpty(request.RegisterName));
// Note that the above just defines a query without executing it
// Now it can be used inside the main query
var users = (
    from user in _context.Users
    let userChange = userChanges.FirstOrDefault()
    select new
    {
        test = userChange
    }
);