EF core 2.2 - EF core 3.1

когда я использовал EF 2.2, он без проблем передавал этот код:

var resource = locResRepo.GetWhere(i => i.ForApplication.ToLower() == applicationName.ToLower())
            .Where(resourcesConditionExpression)
            .Select(item => new ResourceKeyObject
            {
                Id = item.Id,
                ResourceKey = item.ResourceKey,
                ResourceKeyValues = item.ActualLocalizationTranslation
                .Where(translationConditionExpression)
                .Select(v => new ResourceKeyValues
                {
                    Language = v.Language,
                    KeyValue = v.Value

                }).ToList()
            }).ToList();

Но теперь выдает ошибку:

System.InvalidOperationException: Processing of the LINQ expression '(MaterializeCollectionNavigation(
    navigation: Navigation: LocalizationResources.ActualLocalizationTranslation,
    subquery: (NavigationExpansionExpression
        Source: DbSet<ActualLocalizationTranslation>
            .Where(a => EF.Property<Nullable<int>>(l, "Id") != null && EF.Property<Nullable<int>>(l, "Id") == EF.Property<Nullable<int>>(a, "ResourceId"))
        PendingSelector: a => (NavigationTreeExpression
            Value: (EntityReference: ActualLocalizationTranslation)
            Expression: a)
    )
        .Where(i => EF.Property<Nullable<int>>((NavigationTreeExpression
            Value: (EntityReference: LocalizationResources)
            Expression: l), "Id") != null && EF.Property<Nullable<int>>((NavigationTreeExpression
            Value: (EntityReference: LocalizationResources)
            Expression: l), "Id") == EF.Property<Nullable<int>>(i, "ResourceId")))
    .Where(t => True)' by 'NavigationExpandingExpressionVisitor' failed. This may indicate either a bug or a limitation in EF Core. See https://go.microsoft.com/fwlink/?linkid=2101433 for more detailed information.
   at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor) and so on.....

И я действительно не понимаю, почему ... А может, я что-то знаю, но не знаю, как это реализовать


person Qhori    schedule 30.01.2020    source источник
comment
Вы найдете много дубликатов по этой проблеме - проблема в том, что запрос использует оценку на стороне клиента для частей, которые не могут быть переведены в SQL. Эта функция была предназначена только для покрытия отсутствующих функций EF Core 1.x. EF Core 2.2 уже выдает предупреждения об этом, так как это серьезная проблема. Вместо загрузки, например, всего 5 строк, вы можете загружать 5000000 строк, которые фильтруются на клиенте. В EF Core 3.0 оценка на стороне клиента была окончательно отключена   -  person Panagiotis Kanavos    schedule 30.01.2020
comment
Что касается этого запроса, что делают resourcesConditionExpression и translationConditionExpression? Я подозреваю, что они обращаются к локальным функциям или методам и поэтому не могут быть преобразованы в SQL. Кстати, эти ToLower() вызовы не нужны - сортировка базы данных обычно в чувствительна к регистру. Добавление этого ToLower() испускает LOWER() вызовов, которые не позволяют оптимизатору запросов использовать индексы.   -  person Panagiotis Kanavos    schedule 30.01.2020
comment
BTW EF от 1.0 до 6.3 также не имел оценки на стороне клиента. Это было необходимо только для EF 1.x, который даже не мог преобразовать .GroupBy в правильное предложение GROUP BY.   -  person Panagiotis Kanavos    schedule 30.01.2020
comment
Что такое locResRepo и что GetWhere? В EF нет GetWhere, поэтому мы действительно не знаем, что делает код   -  person Panagiotis Kanavos    schedule 30.01.2020
comment
Вызов ToList() внутри запроса EF - это определенно то, что нельзя перевести, и отличный пример проблемы N + 1 - то, что было раньше, было выполнено по 1 дополнительному запросу для каждой записи во внешнем запрос. Для 100 внешних строк вы получите еще 100 запросов.   -  person Panagiotis Kanavos    schedule 30.01.2020
comment
Что ты пытаешься сделать? Какой фактический запрос LINQ вы хотите выполнить? Некоторые вещи просто невозможно выразить как прикованные вызовы. Например, если вы хотите отфильтровать включенные объекты, вы можете использовать from outer from inner where inner.SomeProp='x'. EF Core пока не может фильтровать включенные объекты в форме связанного вызова. Отфильтрованные включения запланированы для EF Core 5.0.   -  person Panagiotis Kanavos    schedule 30.01.2020
comment
Из исключения кажется, что (отсутствующие) выражения содержат некоторые ненужные выражения. В SQL NULL не равно ничему, даже NULL. Выражение SQL Id=ResourceId никогда не будет соответствовать NULL-идентификаторам, поэтому EF.Property<Nullable<int>>(l, "Id") != null не требуется. Это сравнение подозрительно выглядит как попытка JOIN объектов, у которых нет необходимых отношений, иначе EF сам сгенерирует JOIN для этих столбцов. И это Where(t=>true) не будет сгенерировано EF   -  person Panagiotis Kanavos    schedule 30.01.2020


Ответы (2)


Начиная с версии 3.0 запросы EF Core LINQ больше не обрабатываются на клиенте. подробнее: MSDN

На самом деле я думаю, что ваша проблема может быть в свойстве i.ForApplication, если он выполняет некоторые вычисления.

person Alexbogs    schedule 30.01.2020

Ну я нашел решение. Перед выбором должен быть .ToList () из-за логики EF 3.1

person Qhori    schedule 30.01.2020
comment
На самом деле это не так. Вы также можете использовать AsEnumerable - поэтому вам не нужно составлять список, если вы затем выполните проект, за которым следует ToList. Меньше памяти и GC;) - person TomTom; 30.01.2020