如何使用EF Core将单一实体映射到多个表的正确方法?
摘要:把一个实体类型映射到多个表,官方叫法是 Entity splitting,这个称呼有点难搞,要是翻译为“实体拆分”或“拆分实体”,你第一感觉会不会认为是把一个表拆分为多个实体的意思。可它的含义是正好相反。为了避免大伙伴们产生误解,老周直接叫
把一个实体类型映射到多个表,官方叫法是 Entity splitting,这个称呼有点难搞,要是翻译为“实体拆分”或“拆分实体”,你第一感觉会不会认为是把一个表拆分为多个实体的意思。可它的含义是正好相反。为了避免大伙伴们产生误解,老周直接叫它“一个实体映射到多个表”,虽然不言简,但很意赅。
把一个实体类对应到数据库中的多个表,本质上是啥呢?一对一,是不是?举个例子,看图。
恭喜你猜对了,正如上图所示,假设老周收了几个徒弟,上述三个表其实都是【学生】实体类拆开的。第一个表是学生的基础信息,第二个表是补充信息,第三个表是学生的联系方式。第二、三个表中的行必须与第一个表中的行一一对应。
基于这样的理解,咱们可以得出:第一个表有主键A,第二个表有个外键FA引用主键A,第三个表有个外键FB引用主键A。同时,考虑到第二、三个表中的数据是完全依赖第一个表的,所以,第二、三个表中可以把主键和外键设定为同一个列。说人话就是有一列既做当前表的主键,也做外键引用第一个表。这使得第二、三个表中每一条记录的主键列的值必须与第一个表中的主键列相同。
下面咱们举个例子说明一下。假设有这样一个实体。
/// <summary>
/// 宠物
/// </summary>
public class Pet
{
/// <summary>
/// 主键
/// </summary>
public int PetId { get; set; }
/// <summary>
/// 昵称
/// </summary>
public string NickName { get; set; } = "天外物种";
/// <summary>
/// 体重
/// </summary>
public float? Weight { get; set; }
/// <summary>
/// 体长
/// </summary>
public int? Length { get; set; }
/// <summary>
/// 毛色
/// </summary>
public string? Color { get; set; }
/// <summary>
/// 分类
/// </summary>
public string? Category { get; set; }
/// <summary>
/// 爱好
/// </summary>
public string[] Hobbies { get; set; } = [];
/// <summary>
/// 性格
/// </summary>
public string? Temperament { get; set; }
}
于是我有个想法,把这个实体映射到一个表中好像太长,拆开为三个表多好。
1、基本信息。ID,名称,宠物类别;
2、基础特征。毛色,体长体重等;
3、额外信息。爱好,性格等。
