You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core 7.0.1中Linq GroupBy表达式无法转换问题求助

解决EF Core 7中取每组最新Case的查询转换问题

问题场景

有Case和Property两个实体,一个Property关联多个Case,Case包含PropertyId属性。想要获取每个Property对应的最新Case,同时避免N+1查询,原使用GroupBy+SelectMany的LINQ查询无法被EF Core 7.0.1翻译,抛出转换错误。

原错误查询

private IQueryable<Case> AllActiveCases()
        => _context.Cases.Where(c => c.DeletedAt == null);

// 报错的查询
var result = await AllActiveCases()
                       .GroupBy(c => c.PropertyId)
                       .SelectMany(cases => cases.OrderByDescending(c => c.CreatedAt).Take(1))
                       .AsNoTracking()
                       .ToListAsync(cancellationToken);

错误原因

EF Core的GroupBy是基于SQL的分组逻辑,分组后只能使用聚合函数或分组键,无法直接对分组后的集合执行OrderByDescending+Take(1)这类操作,导致SelectMany无法被翻译成SQL。

可行解决方案

方案1:使用窗口函数(推荐)

利用EF Core支持的RowNumber窗口函数,按PropertyId分组并按CreatedAt倒序排序,取每组的第一条数据:

var result = await AllActiveCases()
    .Select(c => new 
    {
        Case = c,
        RowNum = EF.Functions.RowNumber()
            .Over(partitionBy: c.PropertyId, orderBy: c.CreatedAt descending)
    })
    .Where(x => x.RowNum == 1)
    .Select(x => x.Case)
    .AsNoTracking()
    .ToListAsync(cancellationToken);

这种写法会被EF Core正确翻译成SQL的窗口函数查询,性能高效,适合大数据量场景。

方案2:关联子查询筛选

通过子查询判断当前Case是否为对应Property下的最新记录:

var activeCasesQuery = AllActiveCases();

var result = await activeCasesQuery
    .Where(c => !activeCasesQuery.Any(other => 
        other.PropertyId == c.PropertyId && 
        other.CreatedAt > c.CreatedAt))
    .AsNoTracking()
    .ToListAsync(cancellationToken);

这个逻辑是筛选出"不存在同PropertyId且创建时间更晚的Case"的记录,同样能被EF Core翻译,适合数据量中等的场景。

内容的提问来源于stack exchange,提问作者u05sdb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 10:51:10