参考

Docs – Advanced table mapping

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);
});

效果

有几个点需要注意:

  1. Column 撞名字

    Entity property name 是分开的,不可能会撞名字,但数据库是放在一起的,column name 是有可能撞名字的。

    如果名字一样,类型一样,value 也一样的话,那它会 share column,不然就会报错。

    我们可以添加 column prefix 避免撞名字。

    builder.Property(e => e.Line1).HasMaxLength(256).HasColumnName("ShippingInfo_Line1");
  2. 记得 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的更多相关文章

  1. 【EF Core】Entity Framework Core 批处理语句

    在Entity Framework Core (EF Core)有许多新的功能,最令人期待的功能之一就是批处理语句.那么批处理语句是什么呢?批处理语句意味着它不会为每个插入/更新/删除语句发送单独的请 ...

  2. Entity Framework (EF) Core工具创建一对多和多对多的关系

     一. EntirtyFramework(EF)简介 EntirtyFramework框架是一个轻量级的可扩展版本的流行实体框架数据访问技术,微软官方提供的ORM工具让开发人员节省数据库访问的代码时间 ...

  3. .NET 5/.NET Core使用EF Core 5连接MySQL数据库写入/读取数据示例教程

    本文首发于<.NET 5/.NET Core使用EF Core 5(Entity Framework Core)连接MySQL数据库写入/读取数据示例教程> 前言 在.NET Core/. ...

  4. 在EF Core里面如何使用以前EntityFramework的DbContext.Database.SqlQuery<SomeModel>自定义查询

    问: With Entity Framework Core removing dbData.Database.SqlQuery<SomeModel> I can't find a solu ...

  5. ASP.NET Core 配置 Entity Framework Core - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 配置 Entity Framework Core - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 配置 Entity Fram ...

  6. 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 ...

  7. 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 ...

  8. 张高兴的 Entity Framework Core 即学即用:(一)创建第一个 EF Core 应用

    写在前面 Entity Framework Core (EF Core) 是 .NET 平台流行的对象关系映射(ORM)框架.虽然 .NET 平台中 ORM 框架有很多,比如 Dapper.NHibe ...

  9. .net core Entity Framework 与 EF Core

    重点讲 Entity Framework Core ! (一)Entity Framework 它是适用于.NET 的对象关系映射程序 (ORM),现在的EF6已经是久经沙场,并经历重重磨难,获得一致 ...

  10. Entity Framework Core(EF Core) 最简单的入门示例

    目录 概述 基于 .NET Core 的 EF Core 入门 创建新项目 更改当前目录 安装 Entity Framework Core 创建模型 创建数据库 使用模型 基于 ASP.NET Cor ...

随机推荐

  1. 全网最适合入门的面向对象编程教程:12 类和对象的Python实现-Python使用logging模块输出程序运行日志

    全网最适合入门的面向对象编程教程:12 类和对象的 Python 实现-Python 使用 logging 模块输出程序运行日志 摘要: 本文主要介绍了日志的定义和作用,以及 Python 内置日志处 ...

  2. Loggie Geek Camp 火热启动,社区大神带你玩开源

    由开源构建的协作模式,正成为描绘数字蓝图.创造美好未来的主航道,中国工商银行.阿里云等组织已经在网易数帆"架构开发.内核开源"理念中与后者达成合作,来自华为.阿里云.中国移动.eB ...

  3. [oeasy]python0015_十六进制_hexadecimal_字节形态_hex函数

    ​ 十六进制(hexadecimal) 回忆上次内容 上次数制可以转化 bin(n)可以把数字转化为 ​​2进制​ binary 接收一个整数(int) 得到一个二进制数形式的字符串 ​ 编辑 数字在 ...

  4. 【ue源码】定制-蓝图部分

    今天在更新UE的伤害系统的时候出现了一个问题: 多个地方频繁调用一个函数,而这个函数肯定做优化,具体就是,把对应数据放入到队列,另外一个地方慢慢消费这个队列, 那么问题出现了,我使用的UE只有Sing ...

  5. wordpress站点转移

    title: wordpress站点转移 date: 2024/7/13 11:11:11 tag: linux学习 categories: wordpress建设 description: 搭建后的 ...

  6. 【Zookeeper】Re01 安装与操作

    Zookeeper基于JDK开发出来的 运行环境至少需要JRE 快速安装JDK: yum install -y java-1.8.0-openjdk-devel.x86_64 # ZK镜像仓库 htt ...

  7. 【Vue】Re04 指令:第二部分

    一.v-on指令 作用是用来将元素绑定事件监听器,触发特定的函数执行一定功能 关键字:事件监听 <!DOCTYPE html> <html lang="en"&g ...

  8. 【Vue】09 Webpack Part5 Vue组件化开发

    [Vue组件文件打包:Vue-Loader] 复制之前上一个项目 然后在我们的src目录中创建App.vue文件 这个文件就是Vue的模块文件 [建议下载IDEA的Vue.js插件] Vue的模块分为 ...

  9. PVE linux_VM 扩容分区

    页面 调整磁盘大小 手动分区 fdisk -l fdisk /dev/sda 对该磁盘进行分区, 输入n并回车,n是"new"新建分区 [root@localhost ~]# fd ...

  10. 全球最大开源模型Grok-1 —— 马斯克的大模型

    Grok官网: https://grok.x.ai/