参考

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. Simple WPF: S3实现MINIO大文件上传并显示上传进度

    最新内容优先发布于个人博客:小虎技术分享站,随后逐步搬运到博客园. 创作不易,如果觉得有用请在Github上为博主点亮一颗小星星吧! 目的 早两天写了一篇S3简单上传文件的小工具,知乎上看到了一个问题 ...

  2. suffix-icon属性隐藏el-select下拉框右边的下拉图标

    <el-form-item label="入库类型" prop="mt_type"> <el-select v-model="for ...

  3. iOS开发基础142-广告归因

    IDFA IDFA是苹果为iOS设备提供的一个唯一标识符,专门用于广告跟踪和相关的营销用途.与之对应的,在Android平台的是谷歌广告ID(Google Advertising ID). IDFA的 ...

  4. 不是,大哥,咱这小门小户的,别搞我CDN流量啊

    分享是最有效的学习方式. 博客:https://blog.ktdaddy.com/ 最近遇上事儿了,老猫的小小博客网站[程序员老猫的博客]被人盗刷CDN流量了.开始的时候收到了欠费的短信也没有怎么去重 ...

  5. [rCore学习笔记 018]实现特权级的切换

    写在前面 本随笔是非常菜的菜鸡写的.如有问题请及时提出. 可以联系:1160712160@qq.com GitHhub:https://github.com/WindDevil (目前啥也没有 本节内 ...

  6. electron安装成功记录

    1.登录官网查看当前最新版本对应的node,注意这里不要看php那个汉化的,他那个是老版本的,node对不上 2.nvm安装一个新的node 3.使用cnpm安装(npm安装还是报错了,记得删node ...

  7. innodb存储引擎了解

    mysql常用的存储引擎分为innodb和myisam 其中innodb具有支持事务,执行行级锁,支持MVCC,外键,自动增长列,崩溃恢复等特性.并且mysql在5.5.5之后是数据的默认存储引擎 文 ...

  8. TCP和KCP协议

    TCP协议 KCP是一个快速可靠协议,能以比 TCP 浪费 10%-20% 的带宽的代价,换取平均延迟降低 30%-40%,且最大延迟降低三倍的传输效果.纯算法实现,并不负责底层协议(如UDP)的收发 ...

  9. 【Lodop】02 C-Lodop手册阅读上手

    版本:4.0.6.2 一.概述 C-Lodop云打印是一款精巧快捷的云打印服务产品,以Lodop功能语句为基础,JS语句实现远程打印 移动设备+Wifi+普通打印机+集中打印 C-Lodop对客户端浏 ...

  10. Apache SeaTunnel社区首位学生Committer诞生!

    采访对象 | 陈炳烨 采访人&编辑 | Debra Chen Apache SeaTunnel社区第一位学生Committer就此诞生!这位来自西安交通大学软件工程专业的同学从较为简单的文档修 ...