При вызове из «VisitLambda» перезапись узла типа «System.Linq.Expressions.ParameterExpression» должна возвращать ненулевое значение - PullRequest
1 голос
/ 27 апреля 2020

у меня 4 таблицы.

1 - Пользователи 2 - UserRole 3 - Роль 4 - AccessLevel

Что мне нужно, когда при входе пользователя в приложение ему будет отправлен список уровней доступа.

Я использую следующий код для этого:

                var userInfo = await Users.Where(x => x.Id == id)
                 .Select(x => new
                 {
                     UserDusplayName = x.Name + x.Family,
                     AccessLevel = x.UserRoles.FirstOrDefault().Role.AccessLevels.ToList()
                 })
                 .Select(v=>new UserInformationDto
                 {
                     DispayName=v.UserDusplayName,
                     AccessUnserInfos=v.AccessLevel.Select(x=>x.Access)
                 }).FirstOrDefaultAsync();

в моей базе данных этот идентификатор имеет AccessLevel.

Однако, когда я отправляю запрос на это, он показывает мне следующее:

При вызове из 'VisitLambda' перезапись узла типа 'System.Linq.Expressions.ParameterExpression' должна возвращать ненулевое значение того же типа. Или же переопределите «VisitLambda» и измените его, чтобы не посещать детей этого типа

В чем проблема с моим кодом? как я могу решить эту проблему ??

1 Ответ

2 голосов
/ 27 апреля 2020

В чем проблема с моим кодом?

Технически проблема не в вашем коде, который является допустимым запросом LINQ, а в ошибках / недостатках транслятора запросов EF Core.

Здесь есть две конструкции

AccessLevel = x.UserRoles.FirstOrDefault().Role.AccessLevels.ToList()

, которые вызывают проблемы с переводчиком EF Core.

Первый вызов ToList(). Хотя он поддерживается в окончательных проекциях (Select), он вызывает проблемы с другими операторами запросов, такими как следующая Select часть

v.AccessLevel.Select(x=>x.Access)

Секунда FirstOrDefault() здесь

x.UserRoles.FirstOrDefault().Role.AccessLevels

т. е. преобразование последовательности в один элемент, затем извлечение из нее дочерней последовательности.

как я могу решить эту проблему?

Сначала удалите ToList() или устраните средний Select. Во-вторых, удалите FirstOrDefault() - бессмысленно или, если действительно необходимо, замените его оператором ограничения эквивалентного набора Take(1). Используйте оператор выравнивания набора SelectMany, чтобы перейти к нужному подмножеству.

Например,

AccessLevel = x.UserRoles.SelectMany(ur => ur.Role.AccessLevels)

должно решить текущую проблему.


Не связано, но поскольку в вашей модели у пользователя много ролей, а у роли много уровней доступа, здесь

AccessUnserInfos = v.AccessLevel.Select(x => x.Access)

вы можете получить повторяющиеся значения, поэтому рассмотрите возможность применения оператора Distinct

AccessUnserInfos = v.AccessLevel.Select(x => x.Access).Distinct()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...