【问题标题】:Get Max from child entity in EF Core从 EF Core 中的子实体获取 Max
【发布时间】:2019-02-20 04:27:24
【问题描述】:

假设我的公司有客户有订单。 在一个搜索查询中,我想以一种将“具有最新订单的公司放在首位”的方式设置订单。 (希望这足够清楚)。

.OrderByDescending(x =>
x.Customers.Max(c => c.Orders.Any() ? 
        y.Orders.Max(o => (DateTime?) o.DateCreatedUtc) 
        : DateTime.MinValue)
) 
  • 如果客户没有订单,则将最新订单日期视为 DateTime.MinValue

目前我收到以下警告: 无法翻译 LINQ 表达式“Max()”并将在本地计算

我们可以重写它以在服务器上进行评估吗?

【问题讨论】:

  • 这和你之前的问题完全一样。确保外部Max(和任何Max)使用可为空的重载,例如x.Customers.Max(c => c.Orders.Max(o => (DateTime?) o.DateCreatedUtc))。或x.Customers.SelectMany(c => c.Orders).Max(o => (DateTime?) o.DateCreatedUtc)
  • 谢谢@IvanStoev。我想知道这个问题是否与更深的孩子的最大值有关。
  • 不客气。实际上嵌套的 Max 可能由于当前 EFC 的另一个限制而无法工作,但 SelectMany 应该。如果没有,请告诉我重新打开问题。
  • SelectMany 成功了。太棒了!

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


【解决方案1】:

最初(我很抱歉)它看起来与 using Max() in Orderby 完全相同 - 确保您使用外部(基本上每个)Max / Min 调用的可空重载,然后您就会得到翻译。

使用可为空的重载仍然是必须的。然而,有一个隐藏的陷阱。 - 当前 EF Core 只能在聚合方法使用带有可选强制转换的简单成员选择器时翻译它们。无论类型是否可为空,任何其他表达式都会导致客户端评估。

幸运的是,有一个简单的解决方案适用于除 Average 之外的所有标准聚合 - 使用 SelectMany(可能不止一个,并且可以与参考导航属性结合)将聚合集展平到包含聚合实体的级别和在该集合上应用聚合函数。

还要确保不要在聚合选择器中使用条件表达式或类似表达式。可空的Max / Min 重载的好处是它为空集返回null,因此不需要包含Any 检查。 nulls 通常按顺序排在第一位,因此通常您不需要特殊的哨兵值。即使您确实需要它们,请确保在聚合调用之后使用 C# ?? 运算符应用它们。

话虽如此,示例 sn-p 的可翻译版本是

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

【讨论】:

    猜你喜欢
    • 2020-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-05
    • 1970-01-01
    • 2021-05-14
    • 1970-01-01
    • 2023-02-04
    相关资源
    最近更新 更多