多对多关系EF代码优先



我开始学习MVC,并尝试使用实体框架代码优先的方法创建数据库。我有一个学生表和一个科目表,每个学生都可以有多个科目,一个科目可以有很多学生。链接器表有一个分数列,因为每个学生对每个科目都有不同的分数。我在尝试创建dtabase时遇到一个错误,告诉我在模型生成过程中检测到一个或多个验证错误。这是我的模型。

 public class Course
{
    [Key]
    public int CourseId { get; set; }
    public string CourseName { get; set; }
    public List<Student> Students { get; set; }
}
public class Student
{
     [Key]
    public int StudentId { get; set; }
    public string Name { get; set; }
    public List<Course> Courses { get; set; }
}
public class StudentCourses
{
     [Key]
    public Course Course { get; set; }
     [Key]
    public Student Student { get; set; }
    public double Grade { get; set; }
}
public class CourseDb: DbContext
{
    public DbSet<Course> Courses { get; set; }
    public DbSet<Student> Students { get; set; }
    public DbSet<StudentCourses> StudentCourses { get; set; }

}

我在谷歌上搜索了一下,看到了一些多对多关系的方法,但没有一种方法在链接器表中有额外的属性(Grade属性)。

不幸的是,如果您使用具有附加属性的中间表(或者实际上,如果您定义了一个特定的类来管理该关系,而不是让EF自动处理它),您将失去直接导航属性的能力。

您必须将您的型号更改为:

public class Course
{
    ...
    public List<StudentCourses> Students { get; set; }
}

public class Student
{
    ...
    public List<StudentCourses> Courses { get; set; }
}

然后,例如,如果你正在迭代某个特定学生的课程列表:

@foreach (var course in student.Courses)
{
    @course.Course.CourseName, @course.Grade
}

此外,值得一提的是,这可能会导致1+N的查询,所以如果你要这样做,你应该在查询学生时急切地加载课程:

var student = db.Students.Include('Courses.Course').SingleOrDefault(m => m.StudentId == id);

编辑

实际上你在这里遇到了很多问题。我抓住了第一个,就停在那里,没有注意到还有什么问题。您仍然会遇到错误,因为您在中介表上使用了复合键(学生和课程外键的组合)。这很好,但当您指定多个键时,您还必须指定列顺序:

[Key, Column(Order = 0)]
public Course Course { get; set; }
[Key, Column(Order = 1)]
public Student Student { get; set; }

我也不确定是否可以将Key与导航属性一起使用。我从来没有试过自己做,但它可能会起作用。如果你仍然有错误,我会尝试显式外键属性:

[Key, Column(Order = 0)]
public int CourseId { get; set; }
public Course Course { get; set; }
[Key, Column(Order = 1)]
public int StudentId { get; set; }
public Student Student { get; set; }

最新更新