ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

efcore6.0 从属实体

2022-09-06 17:31:17  阅读:151  来源: 互联网

标签:set 映射 get 实体 efcore6.0 从属 public


概念

普通从属实体就是多个实体类映射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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有