Получить Макс от дочерней сущности в EF Core - PullRequest
0 голосов
/ 19 февраля 2019

Допустим, у меня есть компании, у которых есть клиенты, у которых есть заказы.В одном поисковом запросе я хочу установить порядок таким образом, чтобы «компании сначала получали последние заказы».(Надеюсь, это достаточно ясно).

.OrderByDescending(x =>
x.Customers.Max(c => c.Orders.Any() ? 
        y.Orders.Max(o => (DateTime?) o.DateCreatedUtc) 
        : DateTime.MinValue)
) 
  • Если у клиента нет заказа, рассмотрите последнюю дату заказа как DateTime.MinValue

В настоящее время я получаю это предупреждение: Выражение LINQ 'Max () 'не может быть переведен и будет оцениваться локально

Можем ли мы переписать это для оценки на сервере?

1 Ответ

0 голосов
/ 19 февраля 2019

Изначально (мои извинения) он выглядит точно так же, как с использованием Max () в Orderby - убедитесь, что вы используете обнуляемые перегрузки внешних (по сути, всех) Max / Min вызовов, и вы получитеперевод.

Использование перегрузок Nullable по-прежнему необходимо.Однако есть скрытая ловушка.- в настоящее время EF Core может переводить агрегатные методы, только если они используют простой селектор членов с необязательным приведением.Любое другое выражение вызывает оценку клиента независимо от того, является ли тип обнуляемым или нет.

К счастью, существует простое решение, которое работает для всех стандартных агрегатов, кроме Average - сгладить набор агрегатов с помощью SelectMany (может быть больше одного и может быть объединен со справочными навигационными свойствами) до уровня, содержащегоагрегатирующую сущность и примените агрегатную функцию к этому набору.

Также убедитесь, что не используете условные или аналогичные выражения внутри селектора агрегатов.Хорошая вещь о перегрузках nullable Max / Min состоит в том, что она возвращает null для пустого набора, поэтому нет необходимости включать проверки Any.null s обычно располагаются на первом месте по порядку, поэтому обычно вам не нужны специальные значения для часовых.И даже если они вам нужны, обязательно примените их, используя оператор C # ?? после совокупного вызова.

С учетом всего вышесказанного переведенный вариант фрагмента примера

.OrderByDescending(x => 
    x.Customers.SelectMany(c => c.Orders).Max(o => (DateTime?)o.DateCreatedUtc))
//                  ^                                  ^
//               drill down                    convert to nullable
...