在两个实体间存在多个导航属性(续)

先简化学生和班级之间的关系,然后添加老师类型,在老师类中添加对班级的引用

//班级
    public class SchoolClass
    {
        public int ID { get; set; }
        //班级名字
        public string ClassTitle { get; set; }
        //本班级的学生集合
        [InverseProperty("MyClass")]
        public List<Student> Students { get; set; }
        //班长
        public Student ClassMonitor { get; set; }
        //语文课代表
        public Student Chinese { get; set; }
        //数学课代表
        public Student Mathematics { get; set; }
    }

    //老师
    public class Teacher
    {
        //主键
        public int ID { get; set; }

        //姓名
        public string Name { get; set; }

        //老师作为班主任管理的班级
        public SchoolClass AdminClass { get; set; }
    }

    public class Student
    {
        public int ID { get; set; }
        //姓名
        public string Name { get; set; }
        //学生所在的班级
        public SchoolClass MyClass { get; set; }

    }

 

 可以看到,单边导航还是自动给自己加外键。现在在班级类里添加三个老师属性,看如何

  public class SchoolClass
    {
        public int ID { get; set; }
        //班级名字
        public string ClassTitle { get; set; }
        //本班级的学生集合
        [InverseProperty("MyClass")]
        public List<Student> Students { get; set; }
        //班长
        public Student ClassMonitor { get; set; }
        //语文课代表
        public Student Chinese { get; set; }
        //数学课代表
        public Student Mathematics { get; set; }

        //班主任
        public Teacher HeadTeacher { get; set; }

        //语文老师
        public Teacher ChineseTeacher { get; set; }

        //数学老师
        public Teacher MathTeacher { get; set; }
    }

执行migration 出错

Unable to determine the relationship represented by navigation 'SchoolClass.HeadTeacher' of type 'Teacher'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.

因为现在是双边导航了,得给引用属性少的一方指定反导航属性,这样事情简单点,那我们给老师类里的所在班级指定反导航属性,HeadTeacher增加 [InverseProperty("AdminClass")],看看应该能解决吧。

    public class SchoolClass
    {
        public int ID { get; set; }
        //班级名字
        public string ClassTitle { get; set; }
        //本班级的学生集合
        [InverseProperty("MyClass")]
        public List<Student> Students { get; set; }
        //班长
        public Student ClassMonitor { get; set; }
        //语文课代表
        public Student Chinese { get; set; }
        //数学课代表
        public Student Mathematics { get; set; }

        //班主任
        [InverseProperty("AdminClass")]
        public Teacher HeadTeacher { get; set; }

        //语文老师
        public Teacher ChineseTeacher { get; set; }

        //数学老师
        public Teacher MathTeacher { get; set; }
    }

 

什么?还报错

The dependent side could not be determined for the one-to-one relationship between 'Teacher.AdminClass' and 'SchoolClass.HeadTeacher'. To identify the dependent side of the relationship, configure the foreign key property. If these navigations should not be part of the same relationship, configure them independently via separate method chains in 'OnModelCreating'

原来指定反导航属性后变成了一对一的关系,那么需要在其中一方指定外键,如果逻辑上没有一对一的关系,分别老老实实的配自己的外键,就这么简单。

这里老师和班主任之间逻辑上是一对一的关系,那我们在老师类里添加外键 AdminClassID

考虑到每个老师都不可能是班主任,所以外键是可以为空的,因此AdminClassID属性应该是可空的。再改一下

    public class Teacher
    {
        //主键
        public int ID { get; set; }

        //姓名
        public string Name { get; set; }
        //不是每个老师都是班主任
        public int? AdminClassID { get; set; }
        //老师作为班主任管理的班级
        public SchoolClass AdminClass { get; set; }
    }

EF Core多对一关系配置要点:

  1. A实体引用多个B导航属性,B实体引用一个A导航属性;
  2. A实体类注明其中一个B导航属性为InverseProperty,让B实体的导航属性和A实体里面的其中一个导航属性变成一对一的关系;
  3. B实体类定义A导航属性的外键ID为可空值类型(根据实际逻辑考虑,绝对一对一就不能为可空值)

 

posted @ 2020-11-22 10:16  LearningAlbum  阅读(386)  评论(0)    收藏  举报