EF Core 3.1中如何编写对应多表关联分组SQL的Lambda查询
原代码问题
你原有代码存在2个核心错误:
- 使用
Any筛选关联数据仅做存在性过滤,不会实际关联TableB、TableC参与统计,计数逻辑和原SQL的内连接后统计行数的逻辑完全不符 - 末尾冗余的二次
GroupBy(g => g.Id)属于多余逻辑,和原SQL语义不符
正确Lambda写法
写法1:显式Join(和原SQL结构完全对应
var result = await _dbContext.TableA // 内连接TableB并前置过滤Status为Approved的条目 .Join( _dbContext.TableB.Where(b => b.Status == "Approved"), a => a.Id, b => b.aId, (a, b) => new { A = a, B = b } ) // 内连接TableC并前置过滤Scope为Scope1的条目 .Join( _dbContext.TableC.Where(c => c.Scope == "Scope1"), ab => ab.B.Id, c => c.BId, (ab, c) => new { ab.A, C = c } ) // 按TableA的三个字段分组,对应原SQL的group by逻辑 .GroupBy(x => new { x.A.Id, x.A.Name, x.A.SomeNumber }) // 投影输出结果 .Select(g => new { g.Key.Id, g.Key.Name, g.Key.SomeNumber, Count = g.Count() }) .ToListAsync();
写法2:导航属性简化写法(如果实体已配置正确关联关系
TableA配置ICollection<TableB> TableBs导航属性、TableB配置ICollection<TableC> TableCs导航属性时可以用更简洁的写法:
var result = await _dbContext.TableA .SelectMany(a => a.TableBs .Where(b => b.Status == "Approved") .SelectMany(b => b.TableCs .Where(c => c.Scope == "Scope1") .Select(c => new { a, c }) ) ) .GroupBy(x => new { x.a.Id, x.a.Name, x.a.SomeNumber }) .Select(g => new { g.Key.Id, g.Key.Name, g.Key.SomeNumber, Count = g.Count() }) .ToListAsync();
补充说明
你原SQL中select c.Id, c.Name但group by a.Id, a.Name属于SQL语法错误,手误的可能性较高,上述代码默认按照group by的a表字段输出,如果你确实需要输出c表字段,调整Select投影部分的字段取值即可。
内容的提问来源于stack exchange,提问作者Maciejj
相关产品推荐
相关产品推荐

