EF自我理解: 一对一 一对多 多对多

时间:2021-02-21 11:55:35

一,一对一关系。

如:一个student,对应一个studentDetail。

1,student类:

    public class Student : FullAuditedAggregateRoot<long>
    {
        public virtual StudentDetail StudentDetail { get; set; }//包含一个studentDetail的导航属性后 EF会给两个表形成主外键关系。
    }

2,studentDetail类

   public class StudentDetail : FullAuditedAggregateRoot<long>
    {
    }

3,生成的表结构如下:

EF自我理解: 一对一 一对多 多对多

A表中的一个字段,是B表的主键,那他就可以是A表的外键。在这里,student表中,有一个字段是studentDetail表的主键,所以这个字段就是student表的外键。

 

二,一对多关系。

如:一个班级有多个学生。

1,student类:

    public class Student : FullAuditedAggregateRoot<long>
    {
        public virtual StudentDetail StudentDetail { get; set; }

        public virtual BJClass BJClass { get; set; }//加这个方便访问student的时候把班级信息点出来
    }
}

2,班级类

    /// <summary>
    /// 班级
    /// </summary>
    public class BJClass : FullAuditedAggregateRoot<long>
    {
        public virtual ICollection<Student> Students { get; set; }
    }

3,生成的表结构:

student表:

EF自我理解: 一对一 一对多 多对多

 

班级表:

EF自我理解: 一对一 一对多 多对多

 

 4,一对多中,一的那一方,要不要加上对多的那一方的导航属性?

   比如:student类中,要不要加上 班级BJClass,加上跟不加对表结构生成有没有影响?

  为了验证,这里增加一个student1类,跟上面student类只有一个地方不同,那就是没加BJClass的导航属性,注释掉了。

  public  class Student1 : FullAuditedAggregateRoot<long>
    {
        public virtual StudentDetail StudentDetail { get; set; }

       // public virtual BJClass1 BJClass1 { get; set; } //注释掉
    }
}

班级不变,只是改了类名:

    /// <summary>
    /// 班级1
    /// </summary>
    public class BJClass1 : FullAuditedAggregateRoot<long>
    {
        public virtual ICollection<Student1> Students { get; set; }
    }

生成的表结构:

EF自我理解: 一对一 一对多 多对多

 班级表:

EF自我理解: 一对一 一对多 多对多

 

 结论:在一对多关系中,在一 的那一方,加不加 多 的那一方的导航属性,对表结构的生成是没有影响的。

 

三,多对多。

如:一个学生可以有多门课程  一门课程可以被多个学生学习

学生表:

    /// <summary>
    /// 学生表
    /// </summary>
    public class Student : FullAuditedAggregateRoot<long>
    {
        public virtual StudentDetail StudentDetail { get; set; }

        public virtual BJClass BJClass { get; set; }

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

课程表:

    /// <summary>
    /// 课程表
    /// </summary>
    public class Course : FullAuditedAggregateRoot<long>
    {
        public virtual ICollection<Student> Students { get; set; }
    }

多对多,双方各自包含另一方的集合导航属性,数据库默认会生成中间表,生成的表结构如下:

EF自我理解: 一对一 一对多 多对多

 

 这样生成的中间表,基本可以满足大部分的多对多的需求,但是如果有需要在中间表中添加一些字段,则这种根据EF默认配置的方法显然是无法满足的。

查了网上资料,说出了默认配置之外,还可以用FluentApi对中间表进行配置,但FluentApI配置的方式现在很多人都没怎么用过。

既然我们要在中间表增加字段,那我们为什么不直接自己配置中间表呢?就不需要EF帮我们做默认配置了。

多对多默认配置思路:

1,新建类A,A中包含B的集合导航属性  

2,新建类B,B中也包含A的集合导航属性 

3,EF默认生成中间表AB(但生成的中间表只是默认包含A的id以及B的id,无法按需添加字段)

多对多手动配置中间表思路:

1,新建中间表类AB,按需添加自己需要的字段。

2,新建类A,A中包含中间表AB的集合导航属性(不是包含B)

3,新建类B,B中同样包含中间表AB的集合导航属性。

示例:

一份同意书可以对应多个小服务,一个小服务可以被多个同意书选择。

中间表:

    /// <summary>
    /// 自己配置中间表
    /// </summary>
    public class ConsentFormeSmallService2
    {
        /// <summary>
        /// 小服务id
        /// </summary>
        [Required]
        public virtual long ConsentFormeSmallService2Id { get; set; }

        /// <summary>
        /// 自己新增的字段
        /// </summary>
        public virtual long MyFiled { get; set; }
    }

同意书表:

    /// <summary>
    /// 同意书表
    /// </summary>
    public class ConsentForme : AuditedEntity<long>
    {
        public ICollection<ConsentFromeItem> ConsentFromeItem { get; set; }

      //  public ICollection<ConsentFormeSmallService> ConsentFormeSmallService { get; set; }
        public ICollection<ConsentFormeSmallService2> ConsentFormeSmallService2 { get; set; }
    }

小服务表:

    /// <summary>
    /// 小服务表
    /// </summary>
   public class SmallService : AuditedEntity<long>
    {
     //   public ICollection<ConsentFormeSmallService> ConsentFormeSmallService { get; set; }

        public ICollection<ConsentFormeSmallService2> ConsentFormeSmallService2 { get; set; }
    }

生成的表结构,这里只看中间表:

EF自我理解: 一对一 一对多 多对多

如上所示,中间表中包含两个外键,分别是同意书表、小服务表的id。同时 还有自己按需添加的MyFIled字段,实现了中间表的按需添加。

 

如果不直接操作中间表,则可以不需要写到DBContext里面去:

EF自我理解: 一对一 一对多 多对多