用于从 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 获取;放; 公共虚拟 IList 学生 get;设置; 公共虚拟 IList 课程 获取;放; 学生:公共班级学生 [Key] public int Student_ID get;放; 公共字符串 First_Name 获取;放; 公共字符串 Last_Name 获取;放; 公共字符串电子邮件 获取;放; 公共虚拟 IList Student_Course get;放; 课程:public class Course [Key] public int ID get;放; 公共字符串名称 获取;放; 公共虚拟 IList Student_Courses get;放; 问题编辑器中的引用语法用于引用其他内容,而不是您的问题。即当您从其他地方复制文本时。在提供澄清信息时,请直接edit 回答您的问题。 如果您的Student_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 查询的主要内容,如果未能解决你的问题,请参考以下文章

从 2 个表中获取记录数 - 一对多关系

从 3 个表中获取数据时的 Db2 查询

通过 linq 对实体查询进行分组,以通过加入表来获取具有最新时间戳的一条记录

Laravel 5.3 查询从通过外键连接的 4 个表中获取结果

如何根据搜索关键字 rails 从 2 个表中获取数据

同时从四个表中获取按日期分组的聚合值