其他分享
首页 > 其他分享> > efcore6.0 从属实体

efcore6.0 从属实体

作者:互联网

概念

普通从属实体就是多个实体类映射1个数据库表,
例如:一张表不重要的字段太多,并不是每次查询都需要那么多字段,如果按照常规一个实体类映射一张表,那么每次都要处理那么多字段太麻烦,所以干脆分成两个实体,一个实体包含重要字段,另一个实体包含其他字段即可。
但是,上面只是普通做法,如果你愿意,从属实体也可以单独映射另一张数据库表 ,这种场景也是较常见的,
例如:已经在使用的数据库表,你只是想要自定义增加一些扩展字段,而且不便在原表上增加字段。这时候就需要新增一张新表,那么这个新增表就可以作为从属实体进行映射。

普通从属实体(与主实体映射同一张数据表)

做法很简单,例如如下数据库表:
表名:Person

id name age sex createTime updateTime
1 张三 20 2020-01-01 2022-01-02
2 李四 21 2018-12-22 2022-04-02
3 韩梅梅 23 2021-03-11 2021-03-12
4 lucy 24 2019-03-15 2022-11-22
5 lily 24 2021-11-6 2022-03-26

假设,灰色部分createTime、updateTime俩字段为不常用字段,那么可以分成两个实体进行映射。
主实体类代码:

 public  class Person
    {
        public int ID { get; set; } 
        public string? name { get; set; }  
        public int age { get; set; }  
        public string? sex { get; set; }  
    
      //新建一个导航属性,类型名即是【从属实体类名】,本例为:PersonOthers
       public PersonOthers personOthers1 { get; set; }   
    }

从属实体类代码:

[Owned] //从属实体类要加[Owned]注释
 public  class PersonOthers
    { 
     //与引用导航、集合导航的表连接等不同。从属实体根本不需要任何主键、外键(例如:不需要定义个ID属性与主实体Persen的ID属性连接),直接把指定的字段映射上就好了。
        public Datetime CreateTime   { get; set; }
        public Datetime UpdateTime  { get; set; } 
    }

其实到这里从属实体已经建立完成了,但是,查询时系统会把从属实体的映射字段名强制识别为加统一前缀(例如本例会被识别为:personOthers1_CreateTime,personOthers1_UpdateTime),这样显然是不正确的 。所以必须用Fluent API手动配置映射字段名 ,Fluent API代码如下:

 public partial class myContext : DbContext{
   //..............
   public virtual DbSet<Persen> Persens { get; set; } = null!;
   protected override void OnModelCreating(ModelBuilder modelBuilder)
     {
          modelBuilder.Entity<Persen>(entity =>
            {  
                entity.HasKey(m => m.ID);
                entity.ToTable("Person"); 
             //........................................
          //以下为从属实体代码-------------------
                entity.OwnsOne(p => p.personOthers1, x =>
                                   { 
                                      x.Property(p => p.CreateTime).HasColumnName("createTime");
                                      x.Property(p => p.UpdateTime).HasColumnName("updateTime"); 
                                   }   
                              );
         //从属实编辑结束 -----------------------------
            }
     } 
   } 

注意:从属实体只能在主实体的modelBuilder.Entity< T >中进行配置,不能定义独立的modelBuilder.Entity< T >; 也不能注册一个自己的DbSet< T >。否则会报错,因为从属实体的意思就是主实体的附属实体,不允许单独使用

映射单独表的从属实体(与主实体映射不同的数据表)

数据库表如下
主表表名:Person

id name age sex
1 张三 20
2 李四 21
3 韩梅梅 23
4 lucy 24
5 lily 24

但是主表本身没有创建时间和更新时间的字段,所以必须增加一个包含这俩字段的新表。这时候,新表就必须要有外键了(新表中只要有表示外键的字段即可,未必要在数据库中定义关系,在Fluent API中配置外键也可以)
新表表名:Persentime

pid createTime updateTime
1 2020-01-01 2022-01-02
2 2018-12-22 2022-04-02
3 2021-03-11 2021-03-12
4 2019-03-15 2022-11-22
5 2021-11-6 2022-03-26

假设,新表ID的字段名为pid,与主表的主键字段名id不同。

主实体和从属实体类代码跟上面一样即可,唯一区别是从属实体类要加一个pid属性作为外键:

[Owned] //从属实体类要加[Owned]注释
 public  class PersonOthers  //从属类名还是叫PersonOthers也无妨,可以在Fluent API中配置映射表名为Persontime即可。
    { 
     //如果从属实体映射一张单独的数据表, 那么必须有一个外键字段,本例中为pid。
        public int Pid  { get; set; }   
        public Datetime CreateTime   { get; set; }
        public Datetime UpdateTime  { get; set; } 
    }

可以在Fluent API中配置:

 public partial class myContext : DbContext{
   //..............
   public virtual DbSet<Persen> Persens { get; set; } = null!;
   protected override void OnModelCreating(ModelBuilder modelBuilder)
     {
          modelBuilder.Entity<Persen>(entity =>
            {  
                entity.HasKey(m => m.ID);
                entity.ToTable("Person"); 
             //........................................
          //以下为从属实体代码-------------------
                entity.OwnsOne(p => p.personOthers1, x =>
                                   { 
                                      x.ToTable("Persontime"); //personOthers1映射的数据库表名
                                      x.WithOwner ().HasForeignKey (t=>t.Pid )  //从属实体的外键     
                                                    .HasPrincipalKey (p=>p.ID ); //主实体具有唯一特性的字段(如果这个字段是主实体的主键,那么这句可以省略,例如本例就可以省略。)
                                      x.Property(t => t.Pid).HasColumnName("pid");  //
                                      x.Property(t => t.CreateTime).HasColumnName("createTime");
                                      x.Property(t => t.UpdateTime).HasColumnName("updateTime"); 
                                   }   
                              );
         //从属实体编辑结束 -----------------------------
            }
     } 
   } 

总结

普通从属实体映射单独表的从属实体的区别就是:

  1. 映射单独表的从属实体在实体类中需要定义一个外键属性,而普通从属实体不用。
  2. 映射单独表的从属实体在Fluent API配置中需要指定从属实体的外键主实体的唯一键(如果是主键则不用),而普通从属实体不用。
    除此之外,两者都一样。

标签:set,映射,get,实体,efcore6.0,从属,public
来源: https://www.cnblogs.com/tsgjxr/p/16658677.html