繁体   English   中英

实体框架不翻译 Linq 表达式

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM