используя Max () в Orderby - PullRequest
       45

используя Max () в Orderby

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

У меня есть эта строка, которая работает до тех пор, пока я не включил RelationalEventId.QueryClientEvaluationWarning.

Здесь, скажем, я хочу отсортировать результаты (клиентов) по дате их последнего заказа.

.OrderByDescending(x=>x.orders.Max(y=>y.CreateDate))

После настройки контекста следующим образом я понял, что Макс () не конвертируется в TSql.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    base.OnConfiguring(optionsBuilder);
    optionsBuilder.ConfigureWarnings(warning =>
    {
        warning.Throw(RelationalEventId.QueryClientEvaluationWarning);
    });
}

Ошибка:

InvalidOperationException: Error generated for warning 'Microsoft.EntityFrameworkCore.Query.QueryClientEvaluationWarning: The LINQ expression 'Max()' could not be translated and will be evaluated locally.

Я полагаю, что локальный расчет максимума противоречит лучшей производительности.Есть ли способ рассчитать макс на SQL Server?

Ответы [ 2 ]

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

Если у вас EF Core Ведение журнала включено, вы увидите следующее предупреждение:

=> Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor

Возможно, непреднамеренноиспользование потенциально бросающего агрегатного метода (Min, Max, Average) в подзапросе.Будет использоваться оценка клиента, и оператор выбросит, если данных не существует.Изменение типа результата подзапроса на обнуляемый тип позволит выполнить полный перевод.

По сути, они пытаются сохранить поведение броска вышеупомянутых агрегатных методов в LINQ to Objects.

И решение в последнем предложении.например, если тип CreateDate равен DateTime, то

.OrderByDescending(x => x.orders.Max(y => (DateTime?)y.CreateDate))

будет преобразован в SQL.

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

Когда вы вызываете агрегатные методы (Среднее, Мин., Макс.) В запросе LINQ, используя необнуляемый тип, у него нет другого выбора, кроме как оценивать его локально.

Чтобы избежать этого, приведите значение Maxобнуляемому типу, и он будет оценен в базе данных.

Предполагая, что CreateDate имеет тип DateTime, приведение его к DateTime?(обнуляемый) должен работать.

Вот как должен выглядеть ваш запрос:

.OrderByDescending(x=>x.orders.Max(y=> (DateTime?)y.CreateDate)) 

На этот ответ ссылается официальный репозиторий Github

...