[英]Entity Framework does not translate Linq expression
我有以下数据 model,我需要使用这些条件对ResponseItem
列表进行分组:
Group by ResponseItem.Group
Group by ResponseItem.SubGroup
,但只考虑最近的一个,这意味着考虑ResponseItem.CreationDate
代码:
public class ResponseItem
{
public string Group { get; set; }
public string SubGroup { get; set; }
public double Value { get; set; }
public DateTime CreationDate { get; set; }
}
public class GroupedResponseItem
{
public string Group { get; set; }
public List<ResponseItem> Items { get; set; }
}
方法是:
public List<GroupedResponseItem> GetGroupedData( IQueryable<ResponseItem> responseItems )
{
return responseItems
.OrderByDescending(i => i.CreationDate)
.GroupBy(i => i.Group)
.Select(grp => new GroupedResponseItem()
{
Group = grp.Key,
Items = grp
.GroupBy(i => new { i.SubGroup })
.Select(grp => grp.First())
.Select(i => new ResponseItem()
{
SubGroup = i.SubGroup,
CreationDate = i.CreationDate,
Value = i.Value
}).ToList()
})
.ToList();
}
但我收到一个错误:
'LINQ 表达式 'ProjectionBindingExpression: 0' 无法翻译。 以可翻译的形式重写查询,或通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用显式切换到客户端评估
正如我在标题中提到的,我在 .NET 6 上使用实体框架。
另一方面,如果我不考虑第二组,查询工作正常:
public List<GroupedResponseItem> GetGroupedData(IQueryable<ResponseItem> responseItems)
{
return responseItems
.OrderByDescending(i => i.CreationDate)
.GroupBy(i => i.Group)
.Select(grp => new GroupedResponseItem()
{
Group = grp.Key,
Items = grp
.Select(i => new ResponseItem()
{
SubGroup = i.SubGroup,
CreationDate = i.CreationDate,
Value = i.Value
})
.ToList()
})
.ToList();
}
罪魁祸首似乎是这里的次要投影( Select
)
.GroupBy(i => new { i.SubGroup })
.Select(grp => grp.First()) // <-- (1)
.Select(i => new ResponseItem() // <-- (2)
{
SubGroup = i.SubGroup,
CreationDate = i.CreationDate,
Value = i.Value
})
.ToList()
尽管 EF Core 6.0 改进了GroupBy
的翻译,在分组结果集上有额外的运算符(除了键/聚合,它们具有自然的 SQL 支持),但仍然存在限制/缺陷阻止某些构造的翻译。 特别是多重投影。
很快, GroupBy
之后的Select
必须是最终的 LINQ 运算符。 这有点令人难过,因为中间投影通常有助于翻译,并且通常用于解决 EF Core 限制。 但在这种情况下不是。
对于这个特定查询,投影看起来是多余的,因为组元素的类型与投影类型相同,因此可以简单地删除它
.GroupBy(i => new { i.SubGroup })
.Select(grp => grp.First()) // <-- final projection
.ToList()
所以这是解决方案/解决方法之一。 如果您确实需要投影,因为您正在选择部分列,或者投影到不同的类型,然后将其移动到Select
之后GroupBy
:
.GroupBy(i => new { i.SubGroup })
.Select(grp => grp
.Select(i => new ResponseItem()
{
SubGroup = i.SubGroup,
CreationDate = i.CreationDate,
Value = i.Value
})
.First()
) // <-- final projection
.ToList()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.