using Max() in Orderby

天涯浪子 提交于 2019-12-24 16:45:59

问题


I have this line which runs till I enabled RelationalEventId.QueryClientEvaluationWarning.

Here let's say what I want to do is to sort the results (customers) based on their latest order date.

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

After I configure the context as follow I realised the Max() is not converted to TSql.

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

The error:

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

I assume calculating the max locally is against having a better performance. Is there any way to calculate the max on SQL Server?


回答1:


When you call aggregate methods (Average, Min, Max) in a LINQ query using a non-nullable type, it has no choice but to evaluate it locally.

To avoid this, cast your Max value to a nullable type and it will be evaluated in the database.

Assuming CreateDate is of type DateTime, casting it to DateTime? (nullable) should work.

Here's what your query should look like:

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

This answer referenced from official Github Repo




回答2:


If you have EF Core Logging enabled, you would see the following warning:

=> Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor

Possible unintended use of a potentially throwing aggregate method (Min, Max, Average) in a subquery. Client evaluation will be used and operator will throw if no data exists. Changing the subquery result type to a nullable type will allow full translation.

Basically they are trying to preserve the throwing behavior of the aforementioned aggregate methods in LINQ to Objects.

And the solution is in the last sentence. e.g. if the type of CreateDate is DateTime, then

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

will be translated to SQL.



来源:https://stackoverflow.com/questions/54753362/using-max-in-orderby

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!