c# - 用于从 3 个表中获取数据的 LINQ 查询
问题描述
我正在使用 SQL Server 2017、.Net 4.5 和 EF 核心。
我有以下表格: Student_Course:有 Student_Id、Course_ID 和 Student _Course_ID - pk。
学生:First_Name、Last_Name、Email、Student_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 和 Course 表之间进行映射。
提前致谢。
解决方案
因此,您希望为每个学生提供他的姓名以及他参加的所有课程名称的列表(集合?)。
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(= 所有 Student_Courses 的外键 StudentId 等于 Student 的主键):
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
是学生参加的课程名称列表。列表的长度代表参加过的课程的数量。
如果需要,您可以将此课程列表转换为一个带有名称的字符串。但是我不确定这会提高可读性:
"Windows Services REST in a proper manner"
推荐阅读
- c++ - 在某些平台上损坏的 OpenGL 渲染
- android - 无法解决 React Native Camera MLKit 依赖项
- python - 如何创建菜单?
- fortran - Fortran 中的重载下标运算符
- python - 如何绘制大型数据框
- c# - Asp.Net Core 3 Identity - 来自浏览器的 JWT 中不存在自定义声明
- sql-server - 将验证规则中带有正则表达式的 MS-Access 表迁移到 SQL-Server
- python-3.x - 如何使用 pystemd 控制 systemd 定时 ntp 服务?
- c# - 从 C 到 c# 编组结构和联合
- java - 从 Build 返回一个异步和同步客户端