11 EF Core 表拆分
一、表拆分:EF Core 中支持将两个或多个实体映射到单个表。 这称为表拆分或表共享
若要使用表拆分,则需要将多个实体类型映射到同一个表中
1、一个实体类型的主键与另一个实体类型的主键之间配置至少一个关系
2、将主键映射到相同的列
3、如相同的字段映射到同一列
4、Fluent API配置关系表共享,一个表拆分成两个实体
public class Order { public int Id { get; set; } public OrderStatus? Status { get; set; } public DetailedOrder DetailedOrder { get; set; } //DetailedOrder 是Order的子集,满足条件一 } public class DetailedOrder { public int Id { get; set; } //Id主键和 Order.Id主键会映射为同一列 public OrderStatus? Status { get; set; } public string BillingAddress { get; set; } public string ShippingAddress { get; set; } public byte[] Version { get; set; } }
modelBuilder.Entity<DetailedOrder>(dob => { dob.ToTable("Orders"); dob.Property(o => o.Status).HasColumnName("Status"); //配置两个实体的相同属性映射到表的同一列 }); modelBuilder.Entity<Order>(ob => { ob.ToTable("Orders"); ob.Property(o => o.Status).HasColumnName("Status"); //配置两个实体的相同属性映射到表的同一列
ob.HasOne(o => o.DetailedOrder).WithOne() .HasForeignKey<DetailedOrder>(o => o.Id); }); //配置关系表共享,一个表拆分成两个实体
}
二、固有的实体类型
类的拥有属性的字段生成到同一张表中
1、数据注解方式
public class Order { public int Id { get; set; } public StreetAddress ShippingAddress { get; set; } // } [Owned] //Microsoft.EntityFrameworkCore命名空间 public class StreetAddress //设置Owned可以不用设置主键 { public string Street { get; set; } public string City { get; set; } }
注:StreetAddress 属性不需在DbContext继承类中添加DbSet属性
2、Fluent API 配置方式
public class Order { public int Id { get; set; } public StreetAddress ShippingAddress1 { get; set; } // } public class StreetAddress { public string Street { get; set; } public string City { get; set; } } 注:StreetAddress 属性不需在DbContext继承类中添加DbSet属性
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Order>().OwnsOne(o=>o.StreetAddress1); //配置StreetAddress1是Order的拥有属性,StreetAddress1、Order的字段会映射到同一张表中
//modelBuilder.Entity<Order>().OwnsOne(typeof(StreetAddress1), "ShippingAddress1"); //如果Order.ShippingAddress1是私有属性(private StreetAddress ShippingAddress1 { get; set; }
)
)
base.OnModelCreating(modelBuilder); }
3、配置拥有属性里的字段信息
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Order>().OwnsOne(p => p.StreetAddress1, sa => { sa.Property(p => p.Street).HasColumnName("ShipsToStreet") //设置拥有属性里的字段对应表的列名 .HasMaxLength(10); sa.Property(p => p.City).HasColumnName("ShipsToCity"); }); base.OnModelCreating(modelBuilder); }
4、嵌套固有的类型
public class StreetAddress { public string Street { get; set; } public string City { get; set; } } public class OrderDetails { public StreetAddress BillingAddress { get; set; } public StreetAddress ShippingAddress { get; set; } } public class Order { public int Id { get; set; } public OrderDetails OrderDetails { get; set; } }
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Order>().OwnsOne(p => p.OrderDetails, od => { od.OwnsOne(c => c.BillingAddress); //配置嵌套的属性关系 od.OwnsOne(c => c.ShippingAddress); }); base.OnModelCreating(modelBuilder); }
5、将固有类型映射到单独表中
public class StreetAddress { public string Street { get; set; } public string City { get; set; } } public class OrderDetails { public StreetAddress BillingAddress { get; set; } public StreetAddress ShippingAddress { get; set; } } public class Order { public int Id { get; set; } public OrderDetails OrderDetails { get; set; } }
modelBuilder.Entity<DetailedOrder>().OwnsOne(p => p.OrderDetails, od => { od.OwnsOne(c => c.BillingAddress); od.OwnsOne(c => c.ShippingAddress); od.ToTable("OrderDetails"); //设置拥有属性映射到单独的表中 });