EF Core 3.1 (LINQ) - 如何在多列上左加入和分组

Posted

技术标签:

【中文标题】EF Core 3.1 (LINQ) - 如何在多列上左加入和分组【英文标题】:EF Core 3.1 (LINQ) - how to left join and group by on multiple columns 【发布时间】:2021-06-12 22:25:39 【问题描述】:

假设我有 3 个关系: classA(aID#, aName, aNumber), classB(bID#, bName, bNumber, aId), classC(cID#, cName, cNumber, bId)

并根据那 3 个带有一些随机数据的表:

A 类

aID aName aNumber
1 aN1 5
2 aN2 4
3 aN3 3

B类

aID aName aNumber bID
1 bN1 3 1
2 bN2 4 1
3 bN3 5 2

类C

aID aName aNumber bID
1 cN1 6 1
2 cN2 6 2
3 cN3 7 3

现在,使用 T-SQL 语法如下:

select a.aID, a.aName, sum(c.cNumber) as SUM
from classA a 
left join classB b on a.aID = b.aId 
left join classC c on b.bID = c.bId
group by a.AID, a.aName, c.Number

所以我得到这样的结果:

aID aName SUM
1 aN1 12
2 aN2 7
3 aN3 0

如何根据上面的解释创建正确的 lambda 表达式语法?

【问题讨论】:

当我执行该查询时(修正错字后),我在 SUM 列中得到 [6 6 7] (我在求和 c.aNumber 时预期)。见sqlfiddle.com/#!9/850137/2 【参考方案1】:

试试这个查询:

var query =
    from a in ctx.A
    from b in ctx.B.Where(b => a.aID == b.aId).DefaultIfEmpty()
    from c in ctx.C.Where(c => b.bID == c.bId).DefaultIfEmpty()
    group c by new  a.aID, a.aName, c.cNumber  into g
    select new 
    
        g.Key.aID,
        g.Key.aName,
        Sum = g.Sum(x => x.cNumber)
    ;

并使用 LINQ 方法链语法:

var query2 = ctx.A
    .SelectMany(a => ctx.B.Where(b => a.aID   == b.aId).DefaultIfEmpty(), (a, b) => new a, b)
    .SelectMany(t => ctx.C.Where(c => t.b.bID == c.bId).DefaultIfEmpty(), (t, c) => new t, c)
    .GroupBy(t => new t.t.a.aID, t.t.a.aName, t.c.cNumber, t => t.c)
    .Select(g => new g.Key.aID, g.Key.aName, Sum = g.Sum(x => x.cNumber));

【讨论】:

谢谢。但是你能把这个语法转换成 LINQ 方法语法吗? 我可以,但会一团糟。当您有很多连接时,最好保留查询语法。无论如何,ReSharper 可以在点击时做到这一点。

以上是关于EF Core 3.1 (LINQ) - 如何在多列上左加入和分组的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 LINQ 和 EF Core 进行一对多

如何在 EF Core 和 LINQ 中表达 GetDate() 和 DateAdd() 方法?

如何将带有 LEFT JOIN 的 SQL 转换为 EF CORE 3 LINQ

连续获取最大值时如何解决错误(EF Core Linq)? [复制]

LINQ EF Core 左连接 [重复]

无法从 Linq 查询 EF Core 访问字段值