用于从 3 个表中获取数据的 LINQ 查询
Posted
技术标签:
【中文标题】用于从 3 个表中获取数据的 LINQ 查询【英文标题】:LINQ query for getting data from 3 tables 【发布时间】:2021-10-10 21:52:06 【问题描述】:我正在使用 SQL Server 2017、.Net 4.5 和 EF 核心。
我有以下表格: Student_Course:有 Student_Id、Course_ID 和 Student _Course_ID - pk。
学生:名字、姓氏、电子邮件、学生 ID - PK 课程:Id pk,名称
我正在尝试检索学生列表及其各自的 培训班。我还需要每个学生的课程数。
对于上述表格,我在 C# 中有以下实体 Student_Course:具有学生和课程列表的导航属性 学生: 课程:
我正在尝试使用 LINQ 进行此查询:
控制器:
public IList<StudentCourse> GetStudents()
Student_CourseContext scContext = new Student_CourseContext();
var studentCourses = (from sc in scContext.Student_Course
from student in sc.Students.Where( x => x.Student_ID ==
sc.Student_ID)
from course in sc.Courses.Where (x => x.ID == sc.Course_ID)
where sc.Student_ID == student.Student_ID
&& sc.Course_ID == course.ID
&& student.First_Name != "None"
//join course in sc.Courses
//from sc in studentCourseEntity.Student_Courses.GroupBy( x => x.Student_ID)
select new StudentCourse
StudentName = student.First_Name + ' ' + student.Last_Name,
//CourseCount = sc.Gr,
Course = string.Join(",", course.Name)
).ToList();
return studentCourses.ToList();
它正在返回这样的查询:
SELECT ([s0].[First_Name] + CAST(N' ' AS nvarchar(max))) + [s0].[Last_Name], [c].[Name]
FROM [Student_Course] AS [s]
INNER JOIN [Student] AS [s0] ON ([s].[Student_Course_ID] = [s0].[Student_Course_ID]) AND ([s].[Student_ID] = [s0].[Student_ID])
INNER JOIN [Course] AS [c] ON ([s].[Student_Course_ID] = [c].[Student_Course_ID]) AND ([s].[Course_ID] = [c].[ID])
WHERE (([s].[Student_ID] = [s0].[Student_ID]) AND ([s].[Course_ID] = [c].[ID])) AND (([s0].[First_Name] <> N'None') OR [s0].[First_Name] IS NULL)
不是加入指定的列,而是加入 STudent_Course_ID,这是 Student_Course 表的主键。由于这个加入,我收到了错误:
列名“Student_Course_ID”无效。列名“Student_Course_ID”无效。
因为学生和课程表没有这个字段。请让 我知道我怎样才能完成这项工作。
我尝试了 mode.OnCreating 方法来定义之间的关系 这些表,但我能够在 Student、Student_Course 和 课程表。
提前致谢。
【问题讨论】:
Student_Course: public class Student_Course [Key] public int Student_Course_ID get;放; 公共 int Student_ID 获取;放; 公共 int Course_ID 获取;放; 公共虚拟 IListStudent_Course
类是多对多关系的实现,那么最好在该类中为单个学生和用户提供导航属性。我不明白你为什么在那里有列表。
【参考方案1】:
因此,您希望为每个学生提供他的姓名以及他参加的所有课程名称的列表(集合?)。
var studentsWithTheCoursesTheyAttend = dbContext.Students
.Select(student => new
Name = student.First_Name + ' ' + student.Last_Name,
Courses = dbContext.Student_Course
.Where(studentCourse => studentCourse.StudentId == student.Id)
.Select(studentCourse => dbContext.Courses
.Where(course => course.Id == studentCourse.CourseId)
.Select(course => course.Name)
.FirstOrDefault())
.ToList(),
说明:从完整的学生表中的每个学生中取他的名字:
... = dbContext.Students
.Select(student => new
Name = student.First_Name + ' ' + student.Last_Name,
同时选择该学生的所有 Student_Courses(= 外键 StudentId 等于该学生主键的所有 Student_Courses):
Courses = dbContext.Student_Course
.Where(studentCourse => studentCourse.StudentId == student.Id)
您希望从该学生的每个选定 Student_Course 中获取该 Student_Course 所引用的课程的名称。为此,我们将首先获取主键等于外键 StudentCourse.CourseId 的所有课程:
.Select(studentCourse => dbContext.Courses
.Where(course => course.Id == studentCourse.CourseId)
好吧,我们不想要完整的课程,我们只想要它的名称:
.Select(course => course.Name)
好吧,我们知道每个 studentCourse 只会有它所引用的一门课程,而不是零,不超过一门。毕竟,外键studentCourse.CourseId
正好指的是一门课程。
因此我们只需要拿第一个。我本来可以使用First()
,但是IQueryable 中的一些Providers 在使用First 时会报告问题,因此我使用FirstOrDefault()
。
.FirstOrDefault(),
所以到现在为止,我有他的名字,以及他参加的所有课程的名字。将其设为课程列表:
Courses = ...
.ToList(),
所以现在你有这样的东西:
Name = "Sukumar Krishnamurthy",
Courses =
"Advanced .NET",
"All aspects of LINQ",
"Ups and downs of C#",
,
,
Name = "Harald Coppoolse",
Courses =
"Windows Services",
"REST in a proper manner",
,
,
属性Courses
是学生参加的课程名称列表。 List 的长度代表参加过的 Courses 的数量。
如果需要,您可以将此课程列表转换为一个带有名称的字符串。但是我不确定这会提高可读性:
"Windows Services REST in a proper manner"
【讨论】:
以上是关于用于从 3 个表中获取数据的 LINQ 查询的主要内容,如果未能解决你的问题,请参考以下文章
通过 linq 对实体查询进行分组,以通过加入表来获取具有最新时间戳的一条记录