注意:本文描述的是一对一的从属实体(一对多也差不多,只是略有差别,具体可参见MSDN中的EFCORE6.0的文章),也就是一行对应一行。

概念

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

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

做法很简单,例如如下数据库表:
表名: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; }  //新建一个导航属性,类型名即是【从属实体类名】,本例为:PersonOtherspublic 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"); }   );//从属实编辑结束 -----------------------------}} }

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

数据库表如下
主表表名: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配置中需要指定从属实体的外键主实体的唯一键(如果是主键则不用),而普通从属实体不用。
    除此之外,两者都一样。

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

efcore 6.0 从属实体相关推荐

  1. [Asp.net mvc]实体更新异常:存储区更新、插入或删除语句影响到了意外的行数(0)。实体在加载后可能被修改或删除。

    学习asp.net mvc 时在更新实体进行SaveChanges()的时候出现了异常,异常如下: 存储区更新.插入或删除语句影响到了意外的行数(0).实体在加载后可能被修改或删除.刷新 Object ...

  2. 数据库分析与设计练习题(二)基础知识、在IDEF0需求建模方法中,下列关于描述功能活动的图示,正确的是、事务详细编码设计是在下列哪个阶段完成的、下列关于从属实体集的描述,错误的是、各事务尽量按照相同的

    17.在数据库系统生命周期中,通过系统规划与定义来明确系统的目标任务.下列不属于系统规划与定义内容的是 A确定成本预算 B确定任务目标 C确定用户视图 D确定系统边界 参考答案为A 解析:系统规划与定 ...

  3. 脱虚向实,NGK公链让工业4.0赋能实体

    工业4.0是以广泛的工业自动化.高带宽行动网络的兴起,以及物联网(IoT)的发展为标志的最新趋势,而区块链(blockchain)在工业4.0中将有各种潜在应用. 区块链特殊的链接价值的发展方式和体制 ...

  4. EF更新或者删除的时候报错“存储区更新、插入或删除语句影响到了意外的行数(0)。实体在加载后可能被修改或删除“

    ScheduleDown表 主键: ① 字段为MachineNum,类型为String . ②字段ScheduleStart,类型为DateTime. using (MESDB db = new ME ...

  5. 存储区更新、插入或删除语句影响到了意外的行数(0)。实体在加载后可能被修改或删除。

    描述:一般出现这个问题,就是在进行操作数据时,对象的ID的毛病.我遇见这个错误就是在对User表进行操作的时候,没有考虑到ID,直接对对象进行操作,报了上述的错误. 错误原因:如果我们没有ID对我们的 ...

  6. 存储区更新、插入或删除语句影响到了意外的行数(0)。实体在加载后可能被修改或删除。有关了解和处理乐观并发异常的信息

    在使用EF更新数据库内容的时候,提示这个错误 原因:找不到主键,因为我数据库设置的name为主键,切试图更改name的值 解决方法:将数据库的id设为主键,传值的时候不需要传id

  7. 存储区更新、插入或删除语句影响到了意外的行数(0)。实体在加载后可能被修改或删除

    有没有大佬帮忙解决问题谢谢?.

  8. excel能设置从属值集吗_Excel中的从属组合框

    excel能设置从属值集吗 You can add a drop down list in a worksheet cell, so people can select from a list of ...

  9. .NET EFCore之增删改查

    1. 连接数据库 通过依赖注入配置应用程序,通过startup类的ConfigureService方法中的AddDbContext将EFCore添加到依赖注入容器 public void Config ...

最新文章

  1. Linux脚本关联,shell数组和关联数组
  2. Windows Azure Platform Introduction (9) 申请Windows Azure 账户
  3. gerrit的git配置流程
  4. [Qt教程] 第24篇 数据库(四)SQL查询模型QSqlQueryModel
  5. oracle查询中表的连接顺序 手工指定
  6. mysql数据库主从不同步_mysql数据库主从不同步的解决方法
  7. 对atexit函数的理解
  8. web项目开发最佳做法
  9. jvm入门到详解-1
  10. Linux文件与目录的三种时间状态(mtime,atime,ctime)区别
  11. gc计算机术语,GC是什么意思?
  12. 《Python编程从入门到实践》(第2版)第二章 习题答案
  13. 修改电脑开机徽标教程
  14. Python项目通用的目录结构总结
  15. 【TouchDesigner】Feedback的应用NO.3
  16. ASO优化|标题、描述、关键词的最优策略
  17. 毕业季租房的攻略来啦
  18. Python学习,元类type 反射 函数与方法 双下方法
  19. php carbon 中文,Carbon中文使用手册(下)
  20. 计算广告第一章——在线广告综述

热门文章

  1. 《社会动物——爱、性格和成就的潜在根源》读后感及摘录(4)
  2. GPRS 基站定位 LAC CID 得到经度 纬度及百度地图显示
  3. 游戏类如何申请版权保护
  4. linux操作系统(三)linux目录与用户管理
  5. 王捷:边缘计算--物联网场景下的七大数据合规挑战
  6. 使用crm客户管理系统有四大好处
  7. 抓取app数据教程–fiddler抓包数据截取-薄荷app为例
  8. 2022化工自动化控制仪表试题及模拟考试
  9. 川教版计算机四年级上教案,川教版四年级上册信息技术教学计划
  10. SQL Server 中关于EXCEPT和INTERSECT的用法