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");
}
);
//从属实体编辑结束 -----------------------------
}
}
}
总结
普通从属实体
和映射单独表的从属实体
的区别就是:
映射单独表的从属实体
在实体类中需要定义一个外键属性,而普通从属实体
不用。映射单独表的从属实体
在Fluent API配置中需要指定从属实体的外键
、主实体的唯一键(如果是主键则不用)
,而普通从属实体
不用。
除此之外,两者都一样。
标签:set,映射,get,实体,efcore6.0,从属,public 来源: https://www.cnblogs.com/tsgjxr/p/16658677.html