EF学习笔记(十一):实施继承
学习总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理)
上篇链接: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:
最后看看数据库的结果:

最后数据库的结构变为:

EF学习笔记(十一):实施继承的更多相关文章
- EF学习笔记(十二):EF高级应用场景
学习总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 上篇链接:EF学习笔记(十一):实施继承 本篇原文链接:Advanced Entity Framework Scenari ...
- EF学习笔记(十) 处理并发
总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 上一篇:EF学习笔记(九):异步处理和存储过程 本篇原文链接:Handling Concurrency Concurrency ...
- EF学习笔记(九):异步处理和存储过程
总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 上一篇:EF学习笔记(八):更新关联数据 本篇原文:Async and Stored Procedures 为何要采用异步? ...
- EF学习笔记(八):更新关联数据
学习笔记主目录链接:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 上一篇链接:EF学习笔记(七):读取关联数据 本篇原文链接:Updating Related Data 本篇主要考 ...
- python3.4学习笔记(十一) 列表、数组实例
python3.4学习笔记(十一) 列表.数组实例 #python列表,数组类型要相同,python不需要指定数据类型,可以把各种类型打包进去#python列表可以包含整数,浮点数,字符串,对象#创建 ...
- Go语言学习笔记十一: 切片(slice)
Go语言学习笔记十一: 切片(slice) 切片这个概念我是从python语言中学到的,当时感觉这个东西真的比较好用.不像java语言写起来就比较繁琐.不过我觉得未来java语法也会支持的. 定义切片 ...
- 学习笔记——python(继承)
学习笔记(Python继承) 有几种叫法(父类-子类.基类-派生类)先拿代码演示一下: class father: def work(self): print("work>>&g ...
- EF学习笔记(七):读取关联数据
总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本篇参考原文链接:Reading Related Data 本章主要讲述加载显示关联数据: 数据加载分为以下三种 Lazy l ...
- java学习笔记6--类的继承、Object类
接着前面的学习: java学习笔记5--类的方法 java学习笔记4--类与对象的基本概念(2) java学习笔记3--类与对象的基本概念(1) java学习笔记2--数据类型.数组 java学习笔记 ...
随机推荐
- mysql判断表里面一个逗号分隔的字符串是否包含单个字符串、查询结果用逗号分隔
1.mysql判断表里面一个逗号分隔的字符串是否包含单个字符串 : FIND_IN_SET select * from tablename where FIND_IN_SET(传的参数,匹配字段) 例 ...
- 接口测试之——Charles抓包及常见问题解决(转载自https://www.jianshu.com/p/831c0114179f)
简介 Charles其实是一款代理服务器,通过成为电脑或者浏览器的代理,然后截取请求和请求结果达到分析抓包的目的.该软件是用Java写的,能够在Windows,Mac,Linux上使用,安装Charl ...
- 【Spring】Spring3+Spring3MVCの環境構築(中)
参考URL: https://www.cnblogs.com/lnsylt/p/10258457.html ■目録 ■環境設定 ①pom.xml <?xml version="1.0& ...
- excle 内部 超链接(锚点)
超连接对象: 1.文档 2.本文档中的位置. 3. 本文重点 指定 链接到 xx表中的xx位置. 第三种连接 类似于 web文档的中 锚点 超连接 看下图 选 择本文档中的位置, 选择 工作表. ...
- oralce 的安装以及plsql的配置的html连接
https://www.cnblogs.com/xkstudy/p/6400738.html
- taro Object(...) is not a function 版本更新后,H5端运行出错
之前使用taro,版本号1.2.11 会有这样的问题,如下:gitHub找解决的,看到大佬们说更新一下版本就好了,果然更新后,此问题解决OK了. 当然,坑是走不完的,版本也更新挺快的,想着把taro和 ...
- 机器学习入门:Linear Regression与Normal Equation -2017年8月23日22:11:50
本文会讲到: (1)另一种线性回归方法:Normal Equation: (2)Gradient Descent与Normal Equation的优缺点: 前面我们通过Gradient Desce ...
- 分布式ID方案有哪些以及各自的优劣势,我们当如何选择
作者介绍 段同海,就职于达达基础架构团队,主要参与达达分布式ID生成系统,日志采集系统等中间件研发工作. 背景 在分布式系统中,经常需要对大量的数据.消息.http请求等进行唯一标识,例如:在分布式系 ...
- vue中v-model 与 v-bind:value
之前一直认为,v-model相当于下方代码的语法糖,如下: <h1>{{inputValue}}</h1> <input type="text" :v ...
- 文件操作命令(TYPE)
type 命令: // 描述: 显示文本文件的内容. 但不能进行修改. // 语法: type [<Drive>:][<Path>]<FileName> // 参数 ...