Ошибка EF: выражение LINQ не удалось перевести. Происходит с сгенерированным выражением, а не с кодомC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Ошибка EF: выражение LINQ не удалось перевести. Происходит с сгенерированным выражением, а не с кодом

Сообщение Anonymous »

Работая в .NET 8, я создаю метод в своем классе репозитория, который принимает объект с именем Criteria и запрашивает EF на основе условий в этом объекте. Критерий способен генерировать выражение, которое затем передается методу расширения Where() LINQ для запроса. Проблема в том, что для определенного дерева выражений я получаю исключение, которое не возникает, если я предоставляю то же выражение, что и код.
Выражение такое: x => x.UserRoles.Any(y => y.RoleNo == 100101) где x имеет тип UserEntity, y имеет тип UserRoleEntity, а 100101 может быть любым целочисленным идентификатором роли.
При этом возникает следующее исключение: «System.InvalidOperationException: 'Выражение LINQ 'y' не может быть переведено. Либо перепишите запрос в форме, которую можно перевести, либо явно переключитесь на оценку клиента, вставив вызов в «AsEnumerable», «AsAsyncEnumerable», «ToList» или «ToListAsync».
Я также нахожу это исключение неясным, поскольку оно жалуется на «y», который является параметром для вложенная лямбда. Не могу себе представить, что может быть не так в этой части выражения.

Код: Выделить всё

public async Task GetByCriteria(ICriteria criteria)
{
// Using an expression in code
var test = _dbContext.Set()
.Where(x => x.UserRoles.Any(y => y.RoleNo == 100101)).AsNoTracking();

List codeEntities = await test.ToListAsync();
Приведенный выше код работает. Здесь я использую закодированное выражение в вызове Where().

Код: Выделить всё

public async Task GetByCriteria(ICriteria criteria)
{
Expression expression = criteria.AsExpression();

// Using a generated expression
var queryable = _dbContext.Set()
.Where(expression).AsNoTracking();

List exprEntities = await queryable.ToListAsync();
Этот код создает исключение при вызове ToListAsync(). Переменная expression — это выражение, созданное объектом Criteria. В режиме отладки я вижу, что это выражение такое же, как и в предыдущем коде.
Я попробовал запустить закодированное выражение вместо сгенерированного объекта Expression, который показывает, что Я использую правильную лямбду.
Я также пробовал работать с вызовом AsNoTracking() и без него. Это не имеет значения.
Я сравнил объекты Queryable из двух примеров в отладчике и не обнаружил различий между ними.
Я пробовал работает вне отладчика и по-прежнему получает исключение.
Если я помещу оба набора примеров кода вместе, чтобы сначала запускалась закодированная лямбда-выражение, а затем запускалось сгенерированное выражение, исключение < strong>не бывает. Я предполагаю, что это связано с тем, что EF кэшировал первый (успешный) запрос и не пытается снова запросить второй.
ОБНОВЛЕНИЕ:Я рассмотрел PredicateBuilder от LinqKit как возможный способ упростить свой код и облегчить поиск ошибок. К сожалению, он не может сделать то, на что я надеялся. Это упрощает построение выражения верхнего уровня, которое представляет собой серию логических операторов И, но ничего не дает для построения реальных условных выражений, что здесь является самой сложной частью. Мне нужно иметь возможность брать динамические имена свойств, значения и операторы и компоновать их вместе, поэтому, похоже, Expression API по-прежнему остается единственным выходом.
Я продолжу анализировать свои код, чтобы найти разницу между закодированными и сгенерированными выражениями.
ОБНОВЛЕНИЕ:
Я обнаружил проблему и опубликовал подробности ниже в новом ответ. Спасибо всем, кто подал мне идеи.

Подробнее здесь: https://stackoverflow.com/questions/784 ... erated-exp
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»