在Orderby中使用Max()

时间:2019-02-18 18:31:28

标签: c# entity-framework entity-framework-core ef-core-2.2

我有这条线,直到我启用RelationalEventId.QueryClientEvaluationWarning为止。

在这里,我要说的是根据结果(客户)的最新订购日期对其进行排序。

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

按如下方式配置上下文后,我意识到Max()不会转换为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 :(得分:5)

如果启用了EF Core Logging,则会看到以下警告:

  

=> Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor

     

在子查询中可能会意外地使用潜在抛出的聚合方法(最小,最大,平均)。客户评估将被使用,如果    没有数据。将子查询结果类型更改为可为空的类型将允许完整翻译。

基本上,他们试图在LINQ to Objects中保留上述聚合方法的抛出行为。

解决方案在最后一句。例如如果CreateDate的类型为DateTime,则

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

将转换为SQL。

答案 1 :(得分:1)

当您使用不可为null的类型在LINQ查询中调用聚合方法(平均,最小值,最大值)时,除了在本地对其求值,别无选择。

为避免这种情况,请将您的Max值强制转换为可为空的类型,它将在数据库中进行评估。

假设CreateDate的类型为DateTime,是否将其转换为DateTime? (可为空)应该起作用。

查询内容如下:

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

This answer referenced from official Github Repo