首页 > 解决方案 > 实体框架查询特定科目的学生成绩

问题描述

我有 3 个实体:学生

    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public virtual ICollection<Subject> Subjects { get; set; }
    public virtual ICollection<Grade> Grades { get; set; }

主题

    public int SubjectID { get; set; }
    public string SubjectName { get; set; }       
    public virtual ICollection<Student> Students { get; set; }
    public virtual ICollection<Grade> Grades { get; set; }

成绩

    public int GradeID { get; set; }
    public string GradeName { get; set; }
    public int GradeValue { get; set; }

Student 和 Subject 类之间存在多对多关系,并且 Subject-Grade 和 Student-Grade 之间存在一对多。

Student-Grade 的原因:有一种情况,我想显示一个学生的所有成绩,而不考虑学科。对于主题等级:并非每个主题都使用相同的量表,例如,一个主题使用 1-10 的量表,另一个使用 1-100 的量表。

但是,我想显示的是:例如,学生 1 的数学课的所有成绩。

我在想我应该首先获得用户的所有成绩,然后过滤我想要的课程。或者我应该加入所有表格然后过滤 StudentID 和 SubjectID?

所以我的终极问题是,这个查询是怎么做的?

标签: databaseentity-frameworklinq

解决方案


首先,调整你的成绩等级。成绩取决于学生和学科之间的交集。IE

public int GradeID { get; set; }
public string GradeName { get; set; }
public int GradeValue { get; set; }    // -1 = class in progress
public int StudentId { get; set; }
public virtual Student Student { get; set; }
public int SubjectId { get; set; }
public virtual Subject Subject { get; set; }

EF 将生成密钥,因为您拥有导航路径,但如果默认行为发生变化(通常如此),则依赖推断的密钥而不是显式密钥会使您容易受到破坏。另外,您可以控制键的命名。

至于查询,您可以使用:

db.Student.Include("Grades").Include("Grade.Subject").FirstOrDefault(s => s.Id == <something>);

您可能知道,MM 连接需要一个“连接”表。在此示例中,您可以使用 Grades 作为您的 MM 连接表。所以我也会删除学生和学科之间的导航属性。它可以通过目标表和您使用的查询来实现。逆向查询(班级中的学生):

db.Subject.Include("Grades").Include("Grade.Student").FirstOrDefault(s => s.Id == <something>);

推荐阅读