三张表关联:a 对应多个 c(一对多),a 和 b 一对一。关联后按 a、b 分组,c 未参与分组,需要把每组中所有的 c 记录打包成一个列表。
static void Main(string[] args)
{
using (var db = new DataClasses1DataContext())
{
var q = from c in db.Classx
join ci in db.ClassInfo
on c.ID equals ci.ClassID
join s in db.Student
on c.ID equals s.ClassID into stu
from s2 in stu.DefaultIfEmpty()
group new { c, ci, s2 } by new { c, ci } into g
let students = g.Select(m => m.s2).ToList() // 非分组字段打包成列表
select new { g.Key.c, g.Key.ci, students };
var list = q.ToList();
}
}Code language: JavaScript (javascript)
结构拆解:
| 步骤 | 说明 |
|---|---|
join ... into stu + from s2 in stu.DefaultIfEmpty() | 左连接,Classx 可能无学生 |
group new { c, ci, s2 } by new { c, ci } | 按 c、ci 分组,s2 不参与分组 |
let students = g.Select(m => m.s2).ToList() | 每组内所有 s2 打包为列表 |
select new { c, ci, students } | 一个班级一条记录,学生列表挂在下面 |
结果结构示意:
班级A + 班级信息A → students: [张三, 李四]
班级B + 班级信息B → students: [王五]
班级C + 班级信息C → students: []Code language: CSS (css)
关键要点:
| 要点 | 说明 |
|---|---|
group new {a,b,c} | 把三表关联后的完整行作为分组源 |
by new {a,b} | 只按 a、b 分组,c 不进分组键 |
let cs = g.Select(m=>m.c) | 提取每组内所有 c 记录 |
.ToList() | 物化为列表,每个分组一行 |
| 左连接 | into + DefaultIfEmpty() 保证无 c 记录时也有分组行 |
Previous: LINQ to SQL 中使用事务
Next: 多字段排序(orderby)