efcore 6.0 从属实体

本文介绍了EFCore 6.0中从属实体的概念,包括普通从属实体(与主实体映射同一张数据表)和映射独立数据表的从属实体。通过示例详细阐述了如何配置从属实体,特别是在Fluent API中的映射字段名设置以及外键的处理。最后总结了一对一从属实体与映射独立表的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

概念

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

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

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

idnameagesexcreateTimeupdateTime
1张三202020-01-012022-01-02
2李四212018-12-222022-04-02
3韩梅梅232021-03-112021-03-12
4lucy242019-03-152022-11-22
5lily242021-11-62022-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"); 
                                   }   
                              );
         //从属实编辑结束 -----------------------------
            }
     } 
   } 

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

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

idnameagesex
1张三20
2李四21
3韩梅梅23
4lucy24
5lily24

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

pidcreateTimeupdateTime
12020-01-012022-01-02
22018-12-222022-04-02
32021-03-112021-03-12
42019-03-152022-11-22
52021-11-62022-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 >。否则会报错,因为从属实体的意思就是主实体的附属实体,不允许单独使用

ASP.NET Core 6.0 是微软推出的一个跨平台的开发框架。在这个版本中,Entity Framework Core 6.0(EF Core)作为其默认的对象关系映射(ORM)工具,被广泛应用于开发项目。 ASP.NET Core 6.0 中的项目代码主要由以下几个部分组成: 1. 控制器(Controllers):控制器是处理用户请求的核心部分。ASP.NET Core 使用路由来映射 URL 到相应的控制器操作。通过定义不同的动作方法,控制器可以处理 GET、POST、PUT、DELETE 等不同类型的请求,并返回相应的动态页面或数据。 2. 视图(Views):视图是用来展示数据的部分,通常是用 HTML、CSS 和 JavaScript 编写的。ASP.NET Core 中的视图使用 Razor 语法,可以直接访问模型数据并生成动态的 HTML 页面。视图可以与控制器中的动作方法相对应,通过模型和视图数据共同呈现页面内容。 3. 模型(Models):模型是用来定义数据结构和业务逻辑的部分。在 EF Core 中,通过定义实体类来表示数据库表,每个属性对应表中的一列。模型还包括对数据的验证规则以及与数据库的交互。 4. 中间件(Middleware):中间件是位于请求管道中的组件,可以对请求和响应进行处理和转换。ASP.NET Core 6.0 中的中间件可以在请求进入控制器之前或之后对其进行拦截和处理,用于实现身份认证、日志记录、异常处理等功能。 5. 数据访问层(Data Access Layer):在 EF Core 中,数据访问层用于与数据库进行交互。通过 EF Core 提供的 API,开发者可以轻松地执行查询、更新、插入和删除等操作,并且不需要编写大量的原始 SQL 语句。 综上所述,ASP.NET Core 6.0 项目代码包括控制器、视图、模型、中间件和数据访问层等多个部分,它们相互配合完成从用户请求到数据响应的整个过程,实现了一个完整的 Web 应用程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值