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 ...
随机推荐
- 解决方案 | 笔记本电脑能连上WIFI,但是无Internet显示地球图标,怎么回事?(win10)
一.背景 任务栏托盘区显示地球图标,但是实际上可以上网. 疑难诊断一般是这种情况: 二.可能的有效解决方案 0 方案0:使用360断网急救箱傻瓜式修复 个人制作 | 360断网急救箱新版-2.0版单文 ...
- 2024秋招字节跳动朝夕光年UE4客户端开发实习生岗笔试题目
20240117更新 2024年秋招笔试题目,没想到时隔几个月字节跳动游戏业务就要寄了,本文仅供参考,请大佬多多指教 Q1字符串处理 Q2 杯子问题 桌子上有4109+1个饮料杯,这些饮料杯的编号依次 ...
- canvas绘制飞线效果
在我们做的可视化大屏项目中,经常会遇到飞线的效果. 在我们的大屏编辑器中,可以通过拖拽+配置参数的方式很快就能够实现.下面是我们使用大屏编辑器实现的一个项目效果: 中间地图就有飞线的效果. 抛开编辑器 ...
- oeasy教您玩转vim - 91 - # vim脚本编程展望
vim脚本编程展望 回忆 上次我们彻底研究了vim高亮的原理 各种语法项syntax item 关键字keyword 匹配模式match 区域region 定义好了之后还可以设置链接成组 hi d ...
- Nuxt.js 中使用 useHydration 实现数据水合与同步
title: Nuxt.js 中使用 useHydration 实现数据水合与同步 date: 2024/7/18 updated: 2024/7/18 author: cmdragon excerp ...
- AT_tenka1_2015_qualB_b 题解
洛谷链接&Atcoder 链接 本篇题解为此题较简单做法及较少码量,并且码风优良,请放心阅读. 题目简述 给定一个集合形式,判断此集合是 dict 还是 set. 思路 简单的模拟题. 首先需 ...
- Oracle 删除大量表记录操作总结
By:授客 QQ:1033553122 删除表数据操作 清空所有表记录 TRUNCATE TABLE your_table_name; 或者批量删除满足条件的表记录 BEGIN LOOP DELETE ...
- 洛谷[NOIP2015 普及组] 金币
[NOIP2015 普及组] 金币 题目背景 NOIP2015 普及组 T1 题目描述 国王将金币作为工资,发放给忠诚的骑士.第一天,骑士收到一枚金币:之后两天(第二天和第三天),每天收到两枚金币:之 ...
- 【js】 reduce、filter、map 数组链式调用求加和
let data = [ {hierarchy: '香蕉', count: 1}, {hierarchy: '苹果', count: 2}, {hierarchy: '葡萄', count: 3}, ...
- 70%的人都答错了的面试题,vue3的ref是如何实现响应式的?
前言 最近在我的vue源码交流群有位面试官分享了一道他的面试题:vue3的ref是如何实现响应式的?下面有不少小伙伴回答的是Proxy,其实这些小伙伴只回答对了一半. 当ref接收的是一个对象时确实是 ...