[英]EF Core LINQ GROUPBY Then Select to get more than one properties of the entity
我有 2 个表 Outlet 和 Order 具有以下模式:
Outlet Order
------ -------------------
Id Id
Name Name
OrderCompletedTime
NextOrderDueTime
OutletIds
早些时候,当我想使用实体框架核心为每个出口获取 NextOrderDueTime 时,我做了:
return _dbAccessor.RequestContext.MyDbContext.Order
.Where(i => i.OutletId == _dbAccessor.RequestContext.OutletId &&
!i.IsRemoved && i.NextOrderDueTime.HasValue)
.GroupBy(i => i.OutletId)
.Select(g => new { OutletId = g.Key, NextOrderDueTime = g.Min(x => x.NextOrderDueTime) })
.ToDictionary(i => i.OutletId, i => i.NextOrderDueTime);
现在在 UI 上,我们需要将此到期时间作为链接,并希望用户根据订单 ID 导航到该订单详细信息页面
如何更改上述查询以同时返回 OrderId 以及时间?
我的想法:
将方法的返回类型从Dictionary<int, DateTimeOffset?>
更改为Dictionary<int, Tuple<int,DateTimeOffset?>>
我尝试将 Linq 查询更改为:
return _dbAccessor.RequestContext.MyDbContext.Order
.Where(i => i.OutletId == _dbAccessor.RequestContext.OutletId &&
!i.IsRemoved && i.NextOrderDueTime.HasValue)
.GroupBy(i => i.OutletId)
.Select(g =>
new
{
OutletId = g.Key,
NextOrderDueTime = g.FirstOrDefault(x => x.NextOrderDueTime == g.Min(y => y.NextOrderDueTime)).NextOrderDueTime,
NextOrderId = g.FirstOrDefault(x => x.NextOrderDueTime == g.Min(y => y.NextOrderDueTime)).OrderId
})
.ToDictionary(i => i.OutletId, i => new Tuple<int, DateTimeOffset?>(i.NextOrderId, i.NextOrderDueTime));
但这会在运行时引发异常?
请帮助让我知道我在这里做错了什么。
当您返回时,您可以将整个订单连同 outletid 一起拿走:
.Select(g => new {
OutletId = g.Key,
NextOrder = g.OrderBy(x => x.NextOrderDueTime).FirstOrDefault()
})
您可以在此 select 从订单中获取多个属性:
.Select(g => new {
OutletId = g.Key,
NextOrder = g.OrderBy(x => x.NextOrderDueTime).FirstOrDefault()
})
.Select(s => new {
s.OutletId,
NextOrderId = NextOrder.Id,
NextOrder.NextOrderDueTime,
NextOrderName = NextOrder.Name
})
ETC..
要欣赏的主要事情是,分组为您提供了一个具有密钥的 object,但它本身是具有该密钥的所有事物的列表,因此,如果您通过 DUeDat 之类的东西对列表进行排序并获取第一件事,那么您将拥有一个整个 object 具有最低的到期日,您可以从中获取各种东西
The.GroupBy(...).Select(...).ToDictionary(...); 自 EF Core 3.0 起无法转换为 SQL。
由于 EF Core 3.0 中的重大更改。 https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-3.0/break-changes ,EF Core 3.0 将抛出异常以确保您知道所有记录在 Order将在分组和 map 到字典之前从数据库中获取。
我能够让我的查询工作如下:
return _dbAccessor.RequestContext.MyDbContext.Order
.Where(i => i.OutletId == _dbAccessor.RequestContext.OutletId &&
!i.IsRemoved && i.NextOrderDueTime.HasValue).AsEnumerable()
.GroupBy(i => i.OutletId)
.Select(g =>
new
{
OutletId = g.Key,
NextOrderDueTime = g.FirstOrDefault(x => x.NextOrderDueTime == g.Min(y => y.NextOrderDueTime)).NextOrderDueTime,
NextOrderId = g.FirstOrDefault(x => x.NextOrderDueTime == g.Min(y => y.NextOrderDueTime)).OrderId
})
.ToDictionary(i => i.OutletId, i => new Tuple<int, DateTimeOffset?>(i.NextOrderId, i.NextOrderDueTime));
只需在 GroupBy 之前添加 AsEnumerable() 即可完成相同的操作,如另一个答案所示:
_dbAccessor.RequestContext.MyDbContext.Order
.Where(i => i.OutletId == _dbAccessor.RequestContext.OutletId &&
!i.IsRemoved && i.NextOrderDueTime.HasValue).AsEnumerable()
.GroupBy(i => i.OutletId)
.Select(g => new {
OutletId = g.Key,
NextOrder = g.OrderBy(x => x.NextOrderDueTime).FirstOrDefault()
})
.Select(s => new {
s.OutletId,
NextOrderId = NextOrder.Id,
NextOrder.NextOrderDueTime,
NextOrderName = NextOrder.Name
})`enter code here`;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.