如何使用LINQ在SQL Server中连接三个表并生成单行结果?
使用LINQ实现三表关联并合并单行输出的解决方案
嘿,我帮你梳理了用LINQ实现People、Appointment、Participant三表关联,并且把关联的参与者信息合并成单行的方案,先明确下咱们的表结构和期望结果:
数据表结构
People表
| Id | Name | Surname |
|---|---|---|
| 1 | David | David1 |
| 2 | Ameyy | Ameyy2 |
Appointment表
| Id | PeopleId | Subject |
|---|---|---|
| 19 | 1 | description |
Participant表
| Id | AppointmentId | PeopleId |
|---|---|---|
| 1 | 19 | 1 |
| 2 | 19 | 2 |
期望的Result表
| Id | Subject | Participant |
|---|---|---|
| 19 | description | David David1, Ameyy Ameyy2 |
LINQ实现方案
下面分两种场景给你实现代码,你可以根据自己的实际情况选用:
1. 内存集合的LINQ查询(比如处理本地数据)
首先咱们先定义对应的实体类,模拟数据后再做查询:
// 实体类定义 public class People { public int Id { get; set; } public string Name { get; set; } public string Surname { get; set; } } public class Appointment { public int Id { get; set; } public int PeopleId { get; set; } public string Subject { get; set; } } public class Participant { public int Id { get; set; } public int AppointmentId { get; set; } public int PeopleId { get; set; } } // 模拟测试数据 var peopleList = new List<People> { new People { Id = 1, Name = "David", Surname = "David1" }, new People { Id = 2, Name = "Ameyy", Surname = "Ameyy2" } }; var appointmentList = new List<Appointment> { new Appointment { Id = 19, PeopleId = 1, Subject = "description" } }; var participantList = new List<Participant> { new Participant { Id = 1, AppointmentId = 19, PeopleId = 1 }, new Participant { Id = 2, AppointmentId = 19, PeopleId = 2 } }; // 核心关联查询+合并逻辑 var result = from appt in appointmentList join part in participantList on appt.Id equals part.AppointmentId join person in peopleList on part.PeopleId equals person.Id // 按预约的Id和主题分组,保证每个预约一行 group new { person } by new { appt.Id, appt.Subject } into groupedData select new { Id = groupedData.Key.Id, Subject = groupedData.Key.Subject, // 把分组里的参与者姓名用逗号拼接成字符串 Participant = string.Join(", ", groupedData.Select(p => $"{p.person.Name} {p.person.Surname}")) }; // 输出结果看看 foreach (var item in result) { Console.WriteLine($"Id: {item.Id}, Subject: {item.Subject}, Participant: {item.Participant}"); }
2. EF Core中的LINQ查询(直接操作数据库)
如果是用EF Core操作数据库,为了避免把所有数据拉到内存处理,推荐用EF Core 6+版本的特性,它会把string.Join翻译成数据库原生的聚合函数(比如SQL Server的STRING_AGG),性能更优:
// 假设你已经有DbContext,包含三个表的DbSet var result = await _context.Appointments // 关联预约和参与者表 .Join(_context.Participants, appt => appt.Id, part => part.AppointmentId, (appt, part) => new { Appointment = appt, Participant = part }) // 再关联参与者对应的人员表 .Join(_context.People, combined => combined.Participant.PeopleId, person => person.Id, (combined, person) => new { combined.Appointment, Person = person }) // 按预约的Id和主题分组 .GroupBy(data => new { data.Appointment.Id, data.Appointment.Subject }) // 拼接参与者信息 .Select(grouped => new { Id = grouped.Key.Id, Subject = grouped.Key.Subject, Participant = string.Join(", ", grouped.Select(d => $"{d.Person.Name} {d.Person.Surname}")) }) .ToListAsync();
关键点说明
- 核心逻辑是先完成三表关联,再按预约的唯一标识(Id+Subject)分组,最后在分组内把每个参与者的姓名合并成单个字符串。
- 内存场景用
string.Join直接处理分组后的集合;数据库场景下EF Core会自动帮我们把拼接逻辑转换成数据库能执行的SQL,不用自己写原生SQL。
内容的提问来源于stack exchange,提问作者yuksel
相关产品推荐
相关产品推荐

