EF Core – Table / Entity Splitting
参考
Table Splitting
Table Splitting 指的是把一个表映射到多个 Entity,或者反过来说就是把多个 Entity 映射到一个表。
When to use it?
假设我们有一个 Order Entity,Order 有很多信息:CustomerInfo, ShippingInfo, PaymentInfo, TotalAmount 等等等。
如果把所有信息都写进 Order Entity 就会很乱。
比较好的管理方式是创建多几个 Entity:CustomerInfo, ShippingInfo, PaymentInfo,把信息分门别类,各自保管。
然后 Order 和这些 Entity 做一对一关系,这样管理就不乱了。
虽然管理是好了,但这同时也会导致数据库多出几个表,多表就要 join,join 就慢,结果管理好了性能却差了。
要解决这个问题就需要用到 Table Splitting,它可以把多个 Entity 映射到同一个 Table,这样就没有 join 导致的性能问题了。
Step by step
我们看看具体怎么做。
Entity
public class Order
{
public int Id { get; set; }
public CustomerInfo CustomerInfo { get; set; } = null!;
public ShippingInfo ShippingInfo { get; set; } = null!;
public decimal Amount { get; set; }
} public class CustomerInfo
{
public int Id { get; set; }
public Order Order { get; set; } = null!;
public string Name { get; set; } = "";
public string Phone { get; set; } = "";
} public class ShippingInfo
{
public int Id { get; set; }
public Order Order { get; set; } = null!;
public string Line1 { get; set; } = "";
public string Line2 { get; set; } = "";
public string PostalCode { get; set; } = "";
public string Country { get; set; } = "";
}
有 Order, CustomerInfo, ShippingInfo 3 个 Entity。
one-to-one relationships
public class ApplicationDbContext() : DbContext()
{
public DbSet<Order> Orders => Set<Order>(); protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>(
builder =>
{
builder.ToTable("Order");
builder.Property(e => e.Amount).HasPrecision(19, 2);
builder.HasOne(e => e.CustomerInfo).WithOne(e => e.Order).HasForeignKey<CustomerInfo>(e => e.Id);
builder.HasOne(e => e.ShippingInfo).WithOne(e => e.Order).HasForeignKey<ShippingInfo>(e => e.Id);
}); modelBuilder.Entity<CustomerInfo>(
builder =>
{
builder.ToTable("OrderCustomerInfo");
builder.Property(e => e.Name).HasMaxLength(256);
builder.Property(e => e.Phone).HasMaxLength(256);
}); modelBuilder.Entity<ShippingInfo>(
builder =>
{
builder.ToTable("OrderShippingInfo");
builder.Property(e => e.Line1).HasMaxLength(256);
builder.Property(e => e.Line2).HasMaxLength(256);
builder.Property(e => e.PostalCode).HasMaxLength(256);
builder.Property(e => e.Country).HasMaxLength(256);
});
}
}
create Order
using var db = new ApplicationDbContext();
db.Orders.Add(new()
{
Amount = 100,
CustomerInfo = new()
{
Name = "Derrick",
Phone = "+60 16-773 7062",
},
ShippingInfo = new()
{
Line1 = "22, Jalan Perak 7",
Line2 = "Taman Mutiara Rini",
Country = "Malaysia",
PostalCode = "81300"
}
});
db.SaveChanges();
效果



config Table Splitting
只要把 CustomerInfo 和 ShippingInfo 的 ToTable 改成 "Order" 就可以了
modelBuilder.Entity<CustomerInfo>(
builder =>
{
// builder.ToTable("OrderCustomerInfo");
builder.ToTable("Order");
builder.Property(e => e.Name).HasMaxLength(256);
builder.Property(e => e.Phone).HasMaxLength(256);
}); modelBuilder.Entity<ShippingInfo>(
builder =>
{
// builder.ToTable("OrderShippingInfo");
builder.ToTable("Order");
builder.Property(e => e.Line1).HasMaxLength(256);
builder.Property(e => e.Line2).HasMaxLength(256);
builder.Property(e => e.PostalCode).HasMaxLength(256);
builder.Property(e => e.Country).HasMaxLength(256);
});
效果

有几个点需要注意:
Column 撞名字
Entity property name 是分开的,不可能会撞名字,但数据库是放在一起的,column name 是有可能撞名字的。
如果名字一样,类型一样,value 也一样的话,那它会 share column,不然就会报错。
我们可以添加 column prefix 避免撞名字。
builder.Property(e => e.Line1).HasMaxLength(256).HasColumnName("ShippingInfo_Line1");记得 Include
数据库是同表,但是 Entity 是分开的,
在 query 的时候记得要 Include related Entity。
var order = db.Orders
.Include(e => e.CustomerInfo)
.Include(e => e.ShippingInfo)
.First();由于是同表,Include 并不会 translate to left join command。
遇到 RowVersion
如果 Entity 需要 RowVersion 的话,其它所有 Entity 也都跟着需要,不然会遇到鬼。


其它 Entity 可以用 Shadow Property。
Entity Splitting
Entity Splitting 指的是把一个 Entity 映射到多个 Table,或者反过来说就是把多个表映射到一个 Entity。
When to use it?
我也不清楚,只知道这样会导致 join 表,对性能不好。
Step by step
我们看看具体怎么做。
Entity
public class Order
{
public int Id { get; set; }
public decimal Amount { get; set; }
public string CustomerName { get; set; } = "";
public string CustomerPhone { get; set; } = "";
}
CustomerName 和 CustomerPhone 需要映射到另一个 Table。
config Entity Splitting
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>(
builder =>
{
builder.ToTable("Order");
builder.Property(e => e.Amount).HasPrecision(19, 2);
builder.Property(e => e.CustomerName).HasMaxLength(256);
builder.Property(e => e.CustomerPhone).HasMaxLength(256);
builder.SplitToTable("OrderCustomerInfo", tableBuilder =>
{
tableBuilder.Property(e => e.CustomerName).HasColumnName("Name");
tableBuilder.Property(e => e.CustomerPhone).HasColumnName("Phone");
});
});
}
关键就是 SplitToTable 方法
create Order
using var db = new ApplicationDbContext();
db.Orders.Add(new()
{
Amount = 100,
CustomerName = "Derrick",
CustomerPhone = "+60 16-773 7062",
});
db.SaveChanges();
效果


EF Core – Table / Entity Splitting的更多相关文章
- 【EF Core】Entity Framework Core 批处理语句
在Entity Framework Core (EF Core)有许多新的功能,最令人期待的功能之一就是批处理语句.那么批处理语句是什么呢?批处理语句意味着它不会为每个插入/更新/删除语句发送单独的请 ...
- Entity Framework (EF) Core工具创建一对多和多对多的关系
一. EntirtyFramework(EF)简介 EntirtyFramework框架是一个轻量级的可扩展版本的流行实体框架数据访问技术,微软官方提供的ORM工具让开发人员节省数据库访问的代码时间 ...
- .NET 5/.NET Core使用EF Core 5连接MySQL数据库写入/读取数据示例教程
本文首发于<.NET 5/.NET Core使用EF Core 5(Entity Framework Core)连接MySQL数据库写入/读取数据示例教程> 前言 在.NET Core/. ...
- 在EF Core里面如何使用以前EntityFramework的DbContext.Database.SqlQuery<SomeModel>自定义查询
问: With Entity Framework Core removing dbData.Database.SqlQuery<SomeModel> I can't find a solu ...
- ASP.NET Core 配置 Entity Framework Core - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core 配置 Entity Framework Core - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 配置 Entity Fram ...
- ASP.NET Core 开发-Entity Framework (EF) Core 1.0 Database First
ASP.NET Core 开发-Entity Framework Core 1.0 Database First,ASP.NET Core 1.0 EF Core操作数据库. Entity Frame ...
- ASP.NET Core 开发 - Entity Framework (EF) Core
EF Core 1.0 Database First http://www.cnblogs.com/linezero/p/EFCoreDBFirst.html ASP.NET Core 开发 - En ...
- 张高兴的 Entity Framework Core 即学即用:(一)创建第一个 EF Core 应用
写在前面 Entity Framework Core (EF Core) 是 .NET 平台流行的对象关系映射(ORM)框架.虽然 .NET 平台中 ORM 框架有很多,比如 Dapper.NHibe ...
- .net core Entity Framework 与 EF Core
重点讲 Entity Framework Core ! (一)Entity Framework 它是适用于.NET 的对象关系映射程序 (ORM),现在的EF6已经是久经沙场,并经历重重磨难,获得一致 ...
- Entity Framework Core(EF Core) 最简单的入门示例
目录 概述 基于 .NET Core 的 EF Core 入门 创建新项目 更改当前目录 安装 Entity Framework Core 创建模型 创建数据库 使用模型 基于 ASP.NET Cor ...
随机推荐
- 新一代云原生日志架构 - Loggie的设计与实践
Loggie萌芽于网易严选业务的实际需求,成长于严选与数帆的长期共建,持续发展于网易数帆与网易传媒.中国工商银行的紧密协作.广泛的生态,使得项目能够基于业务需求不断完善.成熟.目前已经开源:https ...
- Element-plus的徽章组件el-badge
Element-plus的徽章组件el-badge Element Plus 是一个基于 Vue.js 的 UI 组件库,它提供了一系列的常用 UI 组件供开发者使用.其中,徽章组件(el-badge ...
- Django 多数据库配置与使用总结
Django 多数据库配置与使用总结 By:授客 QQ:103355122 #实践环境 Win 10 Python 3.5.4 Django-2.0.13.tar.gz 官方下载地址: https:/ ...
- CF 1927
G link 定义\({{dp_i}_j}_k\)为考虑完第i个点,最左边没有染色的点为\(j\),最右边没有染色的点为\(k\)的最小数量. 考虑转移(用自己更新别人) 如果不用\(i\),直接转移 ...
- 关于SpringBoot中事务回滚没有生效
在SpringBoot中,事务回滚可以用注解@Transactional标识. Spring声明式事务管理默认对非检查型异常和运行时异常进行事务回滚,而对检查型异常则不进行回滚操作. 1.非检查型异常 ...
- PixiJS源码分析系列:第三章 使用 canvas 作为渲染器
使用 canvasRenderer 渲染 上一章分析了一下 Sprite 在默认 webgl 渲染器上的渲染,这章让我们把目光聚集到 canvasRenderer 上 使用 canvas 渲染器渲染图 ...
- 【Keepalived】KP + NGINX 多机热备学习
案例搭建 环境是三台机器,两台也可以 最后一个IP是测试的VIP 192.168.124.21 centos6-1 192.168.124.22 centos6-2 192.168.124.23 ce ...
- 《Python数据可视化之matplotlib实践》 源码 第二篇 精进 第五章
图 5.1 import matplotlib.pyplot as plt import numpy as np from matplotlib.ticker import AutoMinorLoca ...
- Ubuntu 18.04.4 安装docker18.09 (使用阿里云的源)
由于AI_Station 是使用容器构建环境的,而且只提供镜像上传下载功能,不为容易提供网络功能,因此需要在平台上把镜像拉取到本地,并安装一些必备软件然后再打包成镜像上传回去,因此需要在本地构建doc ...
- 分段树(segment tree)的实现 —— 强化学习中 "优先级回放机制" 的重要组成部分
分段树(segment tree)是强化学习中 "优先级回放机制" 的重要组成部分.本文针对分段树(segment tree)的一个开源版本的实现来进行分析,代码地址: https ...