EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】

前言

α角 与 β角###

关于α角 与 β角的介绍,请见上文 如何用EFCore Lazy Loading实现Entity Split

本篇会继续有关于β角的彩蛋在等着大家去发掘。/斜眼笑

其他###

  • 本篇的程序,可以在 https://github.com/kentliu2007/EFCoreDemo/tree/master/InheritanceWithEntitySplit 下载。建议大家可以下载之后对照着程序来阅读本篇(我用的是VS2017)。
  • 由于篇幅比较长,为了方便阅读,本篇分成两个部分。如果耐着性子看完第一部分,而不是处女座/不是DB First er的,可以止步,不需要继续看第二部分了。

需求###

我们先来看看需求:

  • 某校园的一个人员资料系统,其中可登录用户有两种:教师和学生。每个可登录用户具有以下属性:
    • 用户登录名 (该系统用户的唯一标识值)
    • 密码
  • 教师。系统需要记录 教师 的以下属性:
    • 教职工号码 (某校园里,该教师的唯一标示值)
    • 工资级别 (自编的工资级别)
  • 学生。系统需要记录 学生 的以下属性:
    • 学生编号 (某校园里,该学生的唯一标示值)
    • 学生就读年级

逻辑设计###

根据上述需求,我们会有以下这样的类的设计:

EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】

上述设计还有一个一点点不同的版本:

EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】

物理设计###

从逻辑设计到物理设计,会由于我们选择的具体的实现方式而产生一定的偏差。例如,不同厂商的数据库引擎,或者不选用数据库引擎而选用其他的产品(MQ或者NoSQL类产品),甚至不同的ORM产品,都会引致偏差的发生。

用EF6怎么实现####

下面我们从DB First er的角度,直接根据上述的逻辑设计,设计出数据表。然后再看看用EF6如何实现。

数据表#####

EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】

  • Users的索引

    EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】

    EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】
  • Students的索引

    EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】

    EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】
  • Teachers的索引

    EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】

    EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】
  • FK_Students_Users的设置

    EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】
  • FK_Teachers_Users的设置

    EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】
EF Model#####

在各种wizard的帮助下,逆向工程后,我们需要做一些小改动,删掉某些Property,以及Navigation Property,然后把 Inheritance 关系拉好。并且转换一下 User.UserType为Enum UserTypes。

于是我们就有了这样的 EF Model:

EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】

EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】

EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】

(第一个β角的彩蛋,我们根据习惯,通常会把UserType设置为Enum。这个和逻辑设计有一点点偏差)

EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】

EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】

程序#####
  • Solution

    EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】
  • Unit Test

    EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】
  • 测试数据

    EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】

EF6对类的继承提供了支持,所以从类到表,然后再到EF,一切都很顺其自然,一气呵成。

用EFCore怎么实现####

EFCore也提供类的继承的支持,可以在这里查看微软的文档:https://docs.microsoft.com/zh-cn/ef/core/modeling/inheritance ,以及 https://docs.microsoft.com/zh-cn/ef/core/modeling/relational/inheritance

由于EFCore更加倾向于Code First,所以我们按照文档来走一遍,然后对本篇的需求,就会有以下的产出:

程序#####
  • Solution

    EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】
  • User、Student和Teacher的程序
    public partial class User
{
public string LoginName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
}
public partial class Student : User
{
public string StudentCode { get; set; }
public int GradeLevel { get; set; }
}
public partial class Teacher : User
{
public string StaffCode { get; set; }
public int SalaryGrade { get; set; }
}
  • DBContext的程序

    EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】
  • Unit Test程序

    EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】
数据表#####

有了上述的程序,我们跑一下Migration命令,于是就有以下的表结构

  • Migration命令

    EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】
  • 表结构

    EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】
  • Users的索引

    EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】

没有其他表了?真的没有了。用EF Core的正向工程,上述的三个父子类,它就是生成这样一个数据表,就够了。当然DBA还可能对数据表做一点改动,例如 主键不要是 聚集索引等。不过基于不骗篇幅的借口,让我们偷一下懒吧。

上一篇:spring配置文件一般结构


下一篇:Microsoft Office软件自定义安装目录