从 EF Core 中的子实体获取 Max
Get Max from child entity in EF Core
假设我有一些公司,这些公司的客户有订单。
在一个搜索查询中,我想以一种带来 "companies with latest orders first" 的方式设置顺序。 (希望这足够清楚)。
.OrderByDescending(x =>
x.Customers.Max(c => c.Orders.Any() ?
y.Orders.Max(o => (DateTime?) o.DateCreatedUtc)
: DateTime.MinValue)
)
- 如果客户没有订单,请将最新订单日期视为 DateTime.MinValue
目前我收到此警告:
无法翻译 LINQ 表达式 'Max()',将在本地求值
我们可以重写它以在服务器上进行评估吗?
最初(我很抱歉)它看起来与 完全一样 - 确保您使用外部(基本上每个)Max
/ Min
调用的可空重载并且您得到翻译.
使用可空重载仍然是必须的。然而,有一个隐藏的陷阱。 - 目前 EF Core 只有在使用带有可选转换的简单成员选择器时才能转换聚合方法。无论类型是否可为空,任何其他表达式都会导致客户端评估。
幸运的是,有一个简单的解决方案适用于除 Average
之外的所有标准聚合 - 使用 SelectMany
(可以不止一个,并且可以与参考导航属性结合)将聚合集展平到包含聚合实体的级别并在该集合上应用聚合函数。
还要确保不要在聚合选择器中使用条件表达式或类似表达式。可空 Max
/ Min
重载的好处是它 returns null
用于空集,因此不需要包含 Any
检查。 null
s 通常按顺序排在第一位,因此通常不需要特殊的标记值。即使您确实需要它们,请确保在 聚合调用之后使用 C# ??
运算符 应用它们。
综上所述,示例片段的可翻译版本是
.OrderByDescending(x =>
x.Customers.SelectMany(c => c.Orders).Max(o => (DateTime?)o.DateCreatedUtc))
// ^ ^
// drill down convert to nullable
假设我有一些公司,这些公司的客户有订单。 在一个搜索查询中,我想以一种带来 "companies with latest orders first" 的方式设置顺序。 (希望这足够清楚)。
.OrderByDescending(x =>
x.Customers.Max(c => c.Orders.Any() ?
y.Orders.Max(o => (DateTime?) o.DateCreatedUtc)
: DateTime.MinValue)
)
- 如果客户没有订单,请将最新订单日期视为 DateTime.MinValue
目前我收到此警告: 无法翻译 LINQ 表达式 'Max()',将在本地求值
我们可以重写它以在服务器上进行评估吗?
最初(我很抱歉)它看起来与 Max
/ Min
调用的可空重载并且您得到翻译.
使用可空重载仍然是必须的。然而,有一个隐藏的陷阱。 - 目前 EF Core 只有在使用带有可选转换的简单成员选择器时才能转换聚合方法。无论类型是否可为空,任何其他表达式都会导致客户端评估。
幸运的是,有一个简单的解决方案适用于除 Average
之外的所有标准聚合 - 使用 SelectMany
(可以不止一个,并且可以与参考导航属性结合)将聚合集展平到包含聚合实体的级别并在该集合上应用聚合函数。
还要确保不要在聚合选择器中使用条件表达式或类似表达式。可空 Max
/ Min
重载的好处是它 returns null
用于空集,因此不需要包含 Any
检查。 null
s 通常按顺序排在第一位,因此通常不需要特殊的标记值。即使您确实需要它们,请确保在 聚合调用之后使用 C# ??
运算符 应用它们。
综上所述,示例片段的可翻译版本是
.OrderByDescending(x =>
x.Customers.SelectMany(c => c.Orders).Max(o => (DateTime?)o.DateCreatedUtc))
// ^ ^
// drill down convert to nullable