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 ...
随机推荐
- 基于表单登录的cookies登录
1.基于表单登录的cookies登录 In [ ]: import requests import matplotlib.pyplot as plt from http.cookiejar impor ...
- Swift开发基础07-内存布局
了解Swift的内存布局和底层原理对于编写高性能和内存高效的应用非常重要.接下来,我将更详细地介绍Swift的内存管理机制和一些底层实现细节,包括内存布局.ARC(自动引用计数).引用类型和值类型的区 ...
- 解决阿里云redis监听6379,配置规则也将6379端口开放,但是外网仍无法连接6379的问题
首先确保阿里云配置规则和服务器防火墙已开发6379端口 阿里云linux安装完成redis,并且已经运行,检测6379端口,显示redis-server正在监听,如图 修改redis.conf配置 将 ...
- 数据仓库建模工具之一——Hive学习第三天
1.Hive的基本操作 1.1 Hive库操作 1.1.1 创建数据库 1)创建一个数据库,数据库在HDFS上的默认存储路径是/hive/warehouse/*.db. create database ...
- 学习笔记--Java构造方法
Java构造方法 关于构造方法 构造方法又被称作:构造函数/构造器/Constructor 语法结构: [修饰符列表] 构造方法名(形式参数列表){ 构造方法体; } 对比普通方法语法结构 [修饰符列 ...
- [HTTP] HTTP 协议 Response Header 之 Content-Length、Transfer-Encoding与Content-Encoding
0 引言 在近期项目一场景中,一 Web API (响应内容:7MB - 40MB.数据项:5W-20W条)的网络传输耗时较大,短则 5s,长则高达25s,前端渲染又需要耗时 9s-60s. 在这个场 ...
- 【MongoDB】Re02 文档CRUD
三.文档操作(行记录) 不管comment集合是否存在,直接在comment集合中创建一份文档 > db.comment.insert({"articleid":" ...
- 【转载】PPT上作图转化为矢量图 —— 论文写作必备技能
原文地址: https://www.cnblogs.com/scandit/p/15112138.html PPT作出的图本身就为矢量图(可以插入到Word中),另存为PDF后,再通过PDF专业工具适 ...
- 网友开放的开源项目:网页版的A*算法可视化演示程序
相关项目: https://xueqiaoxu.me/#projects 项目介绍: A JavaScript path-finding library for grid based games. I ...
- 【转载】人工智能CAE仿真分析技术
原文: https://cloud.tencent.com/developer/news/628731 AI与CAE相结合 CAE的本质是对复杂工程问题通过合理简化建立数学模型,并根据输入求得输出.深 ...