在两个实体间存在多个导航属性。

 

当两个实体Entity 存在多个导航属性的时候?数据库生成的是什么情况?

1. 如果是单边的多个导航属性,以引用属性的名字+ID 做为外键设置在当前实体所对应的表上,有多少导航就给自己建多少外键在自己表上,导航属性需要得到值那么就只能通过外键了

   //班级
    public class SchoolClass
    {
        //主键
        public int ID { get; set; }

        //班级名字
        public string ClassTitle { get; set; }

        //班长
        public Student ClassMonitor { get; set; }

        //语文课代表
        public Student Chinese { get; set; }

        //数学课代表
        public Student Mathematics { get; set; }
    }

    //学生
    public class Student
    {
        //主键
        public int ID { get; set; }

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

    }

 

 自称水平一对多

 

2. 我们给SchoolClass 再加一个集合的导航属性。看生成什么表结构?

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

        //班级名字
        public string ClassTitle { get; set; }

        //本班级的学生集合
        public List<Student> Students { get; set; }
        //班长
        public Student ClassMonitor { get; set; }

        //语文课代表
        public Student Chinese { get; set; }

        //数学课代表
        public Student Mathematics { get; set; }
    }

 

 

 原来把集合属性的关系:通过在多方的表上加外键来实现(垂直一对多)。如果再加一个集合属性班级里的所有女生呢?

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

        //班级名字
        public string ClassTitle { get; set; }

        //本班级的学生集合
        public List<Student> Students { get; set; }
        //班里女生
        public List<Student> Girls { get; set; }

        //班长
        public Student ClassMonitor { get; set; }

        //语文课代表
        public Student Chinese { get; set; }

        //数学课代表
        public Student Mathematics { get; set; }
    }

出了黄色的警告,提示需要加外键,要不就按照EF框架发现的顺序 给外键命名

Microsoft.EntityFrameworkCore.Model[10605]
There are multiple relationships between 'Student' and 'SchoolClass' without configured foreign key properties. This will cause Entity Framework to create shadow properties on 'Student' with names dependent on the discovery order.

 

 

 女生集合所对应的外键是SchoolClassID1 

所以这个时候不能让他通过加1来实现,这个该外键登场了。我们给女生集合配置外键看看。

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

        //班级名字
        public string ClassTitle { get; set; }

        //本班级的学生集合
        public List<Student> Students { get; set; }
        //班里女生
        [ForeignKey("SchoolChassId_Girls")]
        public List<Student> Girls { get; set; }

        //班长
        public Student ClassMonitor { get; set; }

        //语文课代表
        public Student Chinese { get; set; }

        //数学课代表
        public Student Mathematics { get; set; }
    }

 

 

 这个时候我们不单边加导航属性了,在student 里面添加一个导航属性看是什么情况?

  //班级
    public class SchoolClass
    {
        //主键
        public int ID { get; set; }

        //班级名字
        public string ClassTitle { get; set; }

        //本班级的学生集合
        public List<Student> Students { get; set; }
        //班里女生
        [ForeignKey("SchoolChassId_Girls")]
        public List<Student> Girls { get; set; }

        //班长
        public Student ClassMonitor { get; set; }

        //语文课代表
        public Student Chinese { get; set; }

        //数学课代表
        public Student Mathematics { get; set; }
    }

    //学生
    public class Student
    {
        //主键
        public int ID { get; set; }

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

        //学生所在的班级
        public SchoolClass MyClass { get; set; }
    }

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

这是因为 添加了双边导航,那么student里面添加的MyClass的反导航属性是谁?这个时候给配上反导航属性 [InverseProperty("MyClass")] 登场,注意:InverseProperty并非只能用在集合上,其它导航属性也是可以的。

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

 

 

 

是不是添加了双边导航,student里面的 MyClass 属性只找SchoolClass 里面的集合属性作为反导航呢?我们去掉两个集合属性,结果报下面这个错。

   public class SchoolClass
    {
        public int ID { get; set; }
        //班级名字
        public string ClassTitle { get; set; }
        //班长
        public Student ClassMonitor { get; set; }
        //语文课代表
        public Student Chinese { get; set; }
        //数学课代表
        public Student Mathematics { get; set; }
    }
    public class Student
    {
        public int ID { get; set; }
        //姓名
        public string Name { get; set; }
        //学生所在的班级
        public SchoolClass MyClass { get; set; }
    }

 

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

 这个时候要么指定反导航关系,要么给自己给自己的导航加外键

 如果手动指定反导航关系就是这个MyClass 与 上面的三个课代表中的任何一个是一对一关系。看你自己的指定了是否有实际意义。

 如果不指定反导航属性,那么它的值从哪里来?只能从自身的外键上来,所以就要配置外键了

 如下:我们不能为了通过migration 而强行设定反导航属性,因为逻辑上他们之间没有必然关系,所以该用外键的老老实实用外键,单飞的有多少设多少,这个观点不一定对,只是个人暂时的理解。

  public class SchoolClass
    {
        public int ID { get; set; }
        //班级名字
        public string ClassTitle { get; set; }
        public int ClassMonitorStudentID { get; set; }
        public Student ClassMonitor { get; set; }
        //语文课代表
        public int ChineseStudentID { get; set; }
        public Student Chinese { get; set; }
        //数学课代表
        public int MathematicsStudentID { get; set; }
        public Student Mathematics { get; set; }
    }

    public class Student
    {
        public int ID { get; set; }
        //姓名
        public string Name { get; set; }
        //学生所在的班级
        public int SchoolClassID { get; set; }
        public SchoolClass MyClass { get; set; }
        ////我的原始班级,现在换班了
        public int OriginalSchoolClassID { get; set; }
        public SchoolClass MyOriginalClass { get; set; }
    }
    modelBuilder.Entity<Student>(
             entity =>
             {
                 entity.HasOne(e => e.MyClass)
                      .WithOne()
                     .HasForeignKey<Student>(e => e.SchoolClassID).OnDelete(DeleteBehavior.NoAction);

                 entity.HasOne(e => e.MyOriginalClass)
                     .WithOne()
                     .HasForeignKey<Student>(e => e.OriginalSchoolClassID).OnDelete(DeleteBehavior.NoAction);
             });
            modelBuilder.Entity<SchoolClass>(
            entity =>
            {
                entity.HasOne(e => e.Chinese)
                     .WithOne()
                    .HasForeignKey<SchoolClass>(e => e.ChineseStudentID).OnDelete(DeleteBehavior.NoAction);

                entity.HasOne(e => e.ClassMonitor)
                    .WithOne()
                    .HasForeignKey<SchoolClass>(e => e.ClassMonitorStudentID).OnDelete(DeleteBehavior.NoAction);
                entity.HasOne(e => e.Mathematics)
                   .WithOne()
                   .HasForeignKey<SchoolClass>(e => e.MathematicsStudentID).OnDelete(DeleteBehavior.NoAction);
            });

 

posted @ 2020-11-21 21:39  LearningAlbum  阅读(482)  评论(0)    收藏  举报