上篇链接:EF学习笔记(十) 处理并发

本篇原文链接:Implementing Inheritance

面向对象的世界里,继承可以很好的重用代码。在本章就对Instructor和Student两个类进行实施继承处理,这两个类有公用的属性,比如LastName等,也有私有的属性;

可以不用增加任何页面,进行修改一些代码,这些修改后的继承关系就会自动反应到数据库中。

通过下图可以看到两个类有哪些公用属性:

那么就可以建一个Person的基础类,让这两个类继承自Persion类:

Options for mapping inheritance to database tables

映射继承到数据库表有以下3种方式:

TPH: table-per-hierarchy

在数据库里就建一个表,里面除了有公有的字段外,既有Student的私有字段,也有Instructor的私有字段;然后再加上一个辨别字段(discriminator)来标明本行是Student还是Instructor,如下图:

TPT: table per type

在数据库里为基础类、继承后的类各生成一张表,表结构就和继承关系一样;

TPC: Table-per-Concrete

就是把所有非抽象的属性都定义到表中,包括来自继承的基类属性;这种方式生成的数据库表就可以和前面没有写继承的时候是一样的;

TPC 和TPH 理论上会有比较好的性能,因为TPT会有大量复杂的SQL Join的操作;

本篇只讲述TPH,TPT和TPC可通过以下链接学习:

Mapping the Table-Per-Type (TPT) Inheritance

Mapping the Table-Per-Concrete Class (TPC) Inheritance

实践操作

先新建一个Person基类:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; namespace EFTest.Models
{
public abstract class Person
{
public int ID { get; set; } [Required]
[StringLength()]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required]
[StringLength(, ErrorMessage = "First name cannot be longer than 50 characters.")]
[Column("FirstName")]
[Display(Name = "First Name")]
public string FirstMidName { get; set; } [Display(Name = "Full Name")]
public string FullName
{
get
{
return LastName + ", " + FirstMidName;
}
}
}
}

然后修改Student和Instructor类,继承自Person类,去除部分代码:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; namespace EFTest.Models
{
public class Instructor : Person
{
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Hire Date")]
public DateTime HireDate { get; set; } public virtual ICollection<Course> Courses { get; set; }
public virtual OfficeAssignment OfficeAssignment { get; set; } }
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; namespace EFTest.Models
{
public class Student:Person
{
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Enrollment Date")]
public DateTime EnrollmentDate { get; set; } public virtual ICollection<Enrollment> Enrollments { get; set; }
} }

SchoolContext.cs中增加:

public DbSet<Person> People { get; set; }

下面就开始迁移数据库,在PMC输入: Add-Migration Inheritance
如果这个时候,直接运行 update-database 会有报错,主要是因为有一些外键存在;

在XXXXXXXX_Inheritance.sc中的up方法中加入以下处理代码:

红色字部分为增加的,注意插入的顺序,

主要工作就是删除原有外键,然后增加一列临时列,把原有Student数据放到新表来;

然后把原来的Enrollement的外键值更新一下,变为新的ID值,再把临时列删除,最后把外键和索引重新再建立:

        public override void Up()
{
// Drop foreign keys and indexes that point to tables we're going to drop.
DropForeignKey("dbo.Enrollment", "StudentID", "dbo.Student");
DropIndex("dbo.Enrollment", new[] { "StudentID" }); RenameTable(name: "dbo.Instructor", newName: "Person");
AddColumn("dbo.Person", "EnrollmentDate", c => c.DateTime());
AddColumn("dbo.Person", "Discriminator", c => c.String(nullable: false, maxLength: ));
AlterColumn("dbo.Person", "HireDate", c => c.DateTime()); AddColumn("dbo.Person", "OldId", c => c.Int(nullable: true)); // Copy existing Student data into new Person table.
Sql("INSERT INTO dbo.Person (LastName, FirstName, HireDate, EnrollmentDate, Discriminator, OldId) SELECT LastName, FirstName, null AS HireDate, EnrollmentDate, 'Student' AS Discriminator, ID AS OldId FROM dbo.Student"); // Fix up existing relationships to match new PK's.
Sql("UPDATE dbo.Enrollment SET StudentId = (SELECT ID FROM dbo.Person WHERE OldId = Enrollment.StudentId AND Discriminator = 'Student')"); // Remove temporary key
DropColumn("dbo.Person", "OldId"); DropTable("dbo.Student"); // Re-create foreign keys and indexes pointing to new table.
AddForeignKey("dbo.Enrollment", "StudentID", "dbo.Person", "ID", cascadeDelete: true);
CreateIndex("dbo.Enrollment", "StudentID"); }

最后执行下 update-database:
最后看看数据库的结果:

最后数据库的结构变为:

【EF6学习笔记】(十一)实施继承的更多相关文章

  1. 【EF6学习笔记】目录

    [EF6学习笔记](一)Code First 方式生成数据库及初始化数据库实际操作 [EF6学习笔记](二)操练 CRUD 增删改查 [EF6学习笔记](三)排序.过滤查询及分页 [EF6学习笔记]( ...

  2. ASP.NET MVC5 及 EF6 学习笔记 - (目录整理)

    个人从传统的CS应用开发(WPF)开始转向BS架构应用开发: 先是采用了最容易上手也是最容易搞不清楚状况的WebForm方式入手:到后面就直接抛弃了服务器控件的开发方式,转而采用 普通页面+Ajax+ ...

  3. EF6学习笔记(四) 弹性连接及命令拦截调试

    EF6学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本章原文地址:Connection Resiliency and Command Interception 原文 ...

  4. EF6 学习笔记(一):Code First 方式生成数据库及初始化数据库实际操作

    EF6 学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本篇参考原文地址: Creating an Entity Framework Data Model 说明:学习 ...

  5. EF6学习笔记(六) 创建复杂的数据模型

    EF6学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本篇原文地址:Creating a More Complex Data Model 本篇讲的比较碎,很多内容本人 ...

  6. EF6 学习笔记(五):数据库迁移及部署

    EF6学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 原文地址:Code First Migrations and Deployment 原文主要讲两部分:开发环境下 ...

  7. EF6 学习笔记(三):排序、过滤查询及分页

    EF6 学习笔记索引目录页: ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 上篇:EF6 学习笔记(二):操练 CRUD 增删改查 本篇原文地址:Sorting, Filterin ...

  8. EF6 学习笔记(二):操练 CRUD 增删改查

    EF6学习笔记总目录 ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 接上篇: EF6 学习笔记(一):Code First 方式生成数据库及初始化数据库实际操作 本篇原文链接: I ...

  9. python3.4学习笔记(十一) 列表、数组实例

    python3.4学习笔记(十一) 列表.数组实例 #python列表,数组类型要相同,python不需要指定数据类型,可以把各种类型打包进去#python列表可以包含整数,浮点数,字符串,对象#创建 ...

  10. Go语言学习笔记十一: 切片(slice)

    Go语言学习笔记十一: 切片(slice) 切片这个概念我是从python语言中学到的,当时感觉这个东西真的比较好用.不像java语言写起来就比较繁琐.不过我觉得未来java语法也会支持的. 定义切片 ...

随机推荐

  1. HDU 6382 odds (暴力 + 剪枝优化)

    odds Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Subm ...

  2. php实现最简单的MVC框架实例教程

    本文以一个实例的形式讲述了PHP实现MVC框架的过程,比较浅显易懂.现分享给大家供大家参考之用.具体分析如下: 首先,在学习一个框架之前,基本上我们都需要知道什么是mvc,即model-view-co ...

  3. VUE项目 npm run build卡住不动,也不报错

    npm config set registry http://registry.cnpmjs.org try again npm run build 居然能动了....

  4. python 队列结合线程的使用

    from queue import Queue from threading import Thread import time q = Queue() def add_to_queue(): for ...

  5. appium+python自动化脚本

    用pycharm,首先得把appium导入,操作如下(否则,运行程序后会报错,没有module appium) Settings->Project Interpreter,双击pip,搜索app ...

  6. 去掉字符空格js

    1. 去掉字符串两端的空格 String.prototype.trim = function () { return this.replace(/(^\s*)|(\s*$)/g, "&quo ...

  7. SSD硬盘安装win10 且安装千牛工作台频繁卡死问题解决过程

    之前win7的时候突然出现卡死现象,具体表现为:磁盘占用百分之百,千牛窗口无法关闭,点截图按钮后,千牛关闭了,并没有截图,千牛聊天输入/无法出现快捷短语了,电脑桌面点击右键没反应,任务栏点击右键也没反 ...

  8. How To Setup a CA

    How To Setup a CA Original Version by Ian AldermanUpdated by Zach Miller Introduction You can set up ...

  9. 在MFC中支持sqlite3

    在vc环境下支持sqlite3的方法有很多,sqlite官网也有推荐sqlitewrappers列表,我选用的是CppSqlite 建立MFC工程的步骤我就不赘述了,以下操作均假设你已经创建好了一个M ...

  10. kaldi的TIMIT实例三

    ============================================================================ MMI + SGMM2 Training &a ...