【问题标题】:How express the many to many relationship with single parent table in EF 5如何在 EF 5 中表达与单父表的多对多关系
【发布时间】:2013-11-27 01:38:31
【问题描述】:

我有一个部门,它可以有很多课程和学生。学生可以链接到许多课程,并且课程可以有许多学生注册。我还希望将学生和课程链接到一个部门。

我如何在 EF/Fluent API 中表达这一点,我已经尝试过这些

        modelBuilder.Entity<Student>().HasRequired(s => s.Department);
        modelBuilder.Entity<Course>().HasRequired(u => u.Department);

        modelBuilder.Entity<Course>()
                    .HasMany(s => s.Students)
                    .WithOptional()
                    .WillCascadeOnDelete(false);
        modelBuilder.Entity<Course>()
                    .HasMany(u => u.Students)
                    .WithMany(s => s.Courses);
        modelBuilder.Entity<Student>()
                    .HasMany(s => s.Courses)
                    .WithOptional()
                    .WillCascadeOnDelete(false);

我也尝试了一些其他组合,但没有任何效果,我现在收到此错误

The navigation property 'Courses' declared on type 'Models.Student' has been configured with conflicting multiplicities.

任何提示/帮助?

更新:学生班级看起来像这样

public class Student
{
    [Key]
    public string Id { get; set; }

    [Required]
    public string SiteName { get; set; }

    public virtual Department Department { get; set; }

    public virtual ICollection<Course> Courses { get; set; }
}

课程:

    public class Course
{
    [Key]
    public string Id { get; set; }

    [Required]
    public string Name { get; set; }


    public virtual Department Department { get; set; }

    public virtual ICollection<Student> Students { get; set; }

}

【问题讨论】:

    标签: c# entity-framework


    【解决方案1】:

    .Entity&lt;Department&gt;() 开始,将所需的导航属性配置为Department,然后指定.WillCascadeOnDelete( false )

    modelBuilder.Entity<Department>()
        .HasMany( d => d.Students )
        .WithRequired()
        .WillCascadeOnDelete( false );
    
    modelBuilder.Entity<Department>()
        .HasMany( d => d.Courses )
        .WithRequired()
        .WillCascadeOnDelete( false );
    
    modelBuilder.Entity<Course>()
        .HasMany(u => u.Students)
        .WithMany(s => s.Courses);
    

    【讨论】:

    • 这没有帮助,我收到了这个错误 Introducing FOREIGN KEY constraint 'FK_dbo.CourseStudents_dbo.Students_Student_Id' on table 'CourseStudents' 可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。
    • 是的,抱歉,删除 WithOptional 但将 WillCascadeOnDelete 移至现有的 .HasMany(...).WithMany(...) 调用;更新示例
    • 无法将 WillCascadeOnDelete 与 WithMany 链接,它无法编译
    • 如果您从我当前的示例中删除 Course.WillCascadeOnDelete(false) 调用,它仍然会给您错误吗?
    • 您使用ICollection&lt;Course&gt; 并使用.WithMany( s =&gt; s.Courses) 配置属性,因此您不应收到冲突的多重性异常。最初,您指定了.WithOptional(),这将导致该异常。
    【解决方案2】:

    这是因为为了进行这样的多对多操作,您需要在表之间创建一个链接表,您可以将其称为 StudentCourses。那么你的StudentCourse 类将有一个StudentCourse 类型的集合。以下是创建类的方法(使用数据注释):

    public class StudentCourses 
    {
        [ForeignKey("Student")]
        public int StudentID { get; set; }
    
        [ForeignKey("Course")]
        public int CourseID { get; set; }
    
        public virtual Student Student { get; set; }
    
        public virtual Course Course { get; set; }
    }
    

    此外,如果您仍然希望能够获取课程中的所有学生(或学生正在学习的所有课程),您可以使用公共属性的 NotMapped 属性轻松完成,如下所示:

    对于您的Student 班级:

    [NotMapped]
    public List<Course> Courses {
      get { return StudentCourses.Select(sc => sc.Course); }
    }
    

    对于您的Course 班级:

    [NotMapped]
    public List<Student> Students {
      get { return StudentCourses.Select(sc => sc.Student); }
    }
    

    【讨论】:

    • 不是必须的,配置.HasMany(...).WithMany(...)会自动生成关系表,同时保留预期的Student.CoursesCourse.Students导航属性
    • 这是否意味着我必须加载三个实体而不是两个? (包括学生课程)?
    • 如果你这样做,那么你会的。但是,生成的 SQL 将保持不变,因为无论如何它都需要生成第三个表来跟踪关系。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-30
    • 1970-01-01
    • 1970-01-01
    • 2016-12-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多