一、Table Per Hierarchy (TPH,默认)

每个层次结构共用一个表,类的每一个属性都必须是可空的。

1、默认行为

只建立一个表,把基类和子类中的所有属性都映射为表中的列。
在这种处理方式中,EF为基类和所有子类共建立一个表,基类和子类中的所有属性都映射为表中的一个列。t默认在这个表中建立一个叫做Discriminator的列,类型是nvarchar,长度是128。
在存储基类或子类的时候,把类名作为Discriminator列的值。

2、Fluent API修改默认行为

modelBuilder.Entity<Course>()
.Map<Course>(m => m.Requires("Type").HasValue("Course"))
.Map<OnsiteCourse>(m => m.Requires("Type").HasValue("OnsiteCourse"));

Map方法中传入的类型参数是子类的类名,Requires用于指定Discriminator列的名字,HasValue用于指定它的类型和每个子类对应的值。

二、Table Per Type(TPT)

每个类就各要一个表。

1、默认行为

为基类和每个子类各建立一个表,每个与子类对应的表中只包含子类特有的属性对应的列。
子类的表中只包含子类特有的属性,子表还会存储一个将子表与基表联接的外键。

2、Fluent API修改默认行为

我们可以使用Map方法强制让Code First使用TPT方式,因为Code First默认使用的是TPC方式。

modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<OnsiteCourse>().ToTable("OnsiteCourse");

三、Table Per ConCrete Type(TPC)

不推荐使用。每个具体的派生类各一个表

1、默认行为

在子类对应的表中除了子类特有的属性外还有基类的属性对应的表。基类可以是abstract

2、Fluent API修改默认行为

通过MapInheritedProperties方法就可以强制Code First使用TPC方式。

modelBuilder.Entity<Course>()
.Property(c => c.CourseID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);--因为属于 TPC 继承层次结构的表并不使用同一个主键,
关闭主键属性的标识,避免为不同字表插入重复的实体键。 modelBuilder.Entity<OnsiteCourse>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable("OnsiteCourse");
}); modelBuilder.Entity<OnlineCourse>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable("OnlineCourse");
});

四、实体拆分

允许一个实体类型的属性分散在多个表中。
实体拆分通过多次调用 Map 方法将一部分属性映射到特定表。
在以下示例中,Department 实体拆分到两个表中:Department 和 DepartmentDetails。

modelBuilder.Entity<Department>() .Map(m =>
{
m.Properties(t => new { t.DepartmentID, t.Name });
m.ToTable("Department");
}).Map(m =>
{
m.Properties(t => new { t.DepartmentID, t.Administrator, t.StartDate, t.Budget });
m.ToTable("DepartmentDetails");
});

五、表拆分

两个实体类型映射到同一个表。

1.两个类必须共享同一个主键。
2.两个类之间的关系必须被映射为表之间的一对一关系。

modelBuilder.Entity<OfficeAssignment>().HasKey(t => t.InstructorID);  --共用组件
modelBuilder.Entity<Instructor>() .HasRequired(t => t.OfficeAssignment).WithRequiredPrincipal(t => t.Instructor);--一对一关系
modelBuilder.Entity<Instructor>().ToTable("Instructor");
modelBuilder.Entity<OfficeAssignment>().ToTable("Instructor");

六、将类指定为复杂类型

1、指定方法:

DataAnnotations方式:[ConlexType]或FluentAPI:modelBuilder.ComplexType<Details>();

注意:
1.复杂类型类不能有主键。
2.复杂类型只能包含.net基础类型的属性。
3.使用复杂类型的类,只能包复杂类型的一个实例,不能使用复杂类型的集合。

2、配置复杂类型的属性

1、可以对 ComplexTypeConfiguration 调用 Property。
modelBuilder.ComplexType<Details>() .Property(t => t.Location).HasMaxLength(20);

public class AddressComplexTypeConfiguration:ComplexTypeConfiguration<Address>
{
public AddressComplexTypeConfiguration()
{
Property(a => a.Country).HasColumnName("Country").HasMaxLength();
Property(a => a.ZipCode).HasColumnName("ZipCode").HasMaxLength();
}
}

2、也可以使用点表示法访问复杂类型的属性。

modelBuilder.Entity<OnsiteCourse>().Property(t => t.Details.Location) .HasMaxLength();

七、DataBase初始化

1、调用Database.SetInitializer方法:

一般Global.ascx.cs,Main应用程序的入口等地方调用Database.SetInitializer方法:

  • 只要Fluent API配置的数据库映射发生变化或者domain中的model发生变化了,就把以前的数据库删除掉,根据新的配置重新建立数据库。

    Database.SetInitializer(new DropCreateDatabaseIfModelChanges<BreakAwayContext>());
  • 只有在没有数据库的时候才会根据数据库连接配置创建新的数据库。这种配置主要用于production环境。
    Database.SetInitializer(new CreateDatabaseIfNotExists<BreakAwayContext>());
  • 不管数据库映射或者model是否发生变化,每次都重新删除并根据配置重建数据库。
    Database.SetInitializer(new DropCreateDatabaseAlways<BreakAwayContext>());

2、通过配置文件更灵活的指定数据库初始化的方式:

<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="DatabaseInitializerForType OrderSystemContext" value="System.Data.Entity.DropCreateDatabaseIfModelChanges[[OrderSystemContext]], EntityFramework" />
</appSettings>
</configuration>

3、自定义数据库初始化类

通过自定的初始化类,还可以将一些基础数据在创建数据库之后插入到数据库中去。

public class DropCreateOrderDatabaseWithSeedValueAlways : DropCreateDatabaseAlways<OrderSystemContext>
{
protected override void Seed(OrderSystemContext context)
{
context.ProductCatalogs.Add(new ProductCatalog { CatalogName = "DELL E6400", Manufactory = "DELL", ListPrice = , NetPrice = });
context.ProductCatalogs.Add(new ProductCatalog { CatalogName = "DELL E6420", Manufactory = "DELL", ListPrice = , NetPrice = });
}
} Database.SetInitializer(new DropCreateOrderDatabaseWithSeedValueAlways());

Code First TPH、TPT、TPC与继承类的更多相关文章

  1. Code First 中的 TPH TPT TPC

    public class Blog { public int Id { get; set; } public DateTime Creationdate { get; set; } public st ...

  2. C++浅析——继承类内存分布和虚析构函数

    继承类研究 1. Code 1.1 Cbase, CTEST为基类,CTest2为其继承类,并重新申明了基类中的同名变量 class CBase { public: int Data; CBase() ...

  3. C#基础-事件 继承类无法直接引发基类的事件

    An event can be raised only from the declaration space in which it is declared. Therefore, a class c ...

  4. IOS 杂笔-1(为什么不继承类簇?)

    答:首先,类簇是可以继承的,并不是不可以.例如,我们可以选择继承NSSting,但是此时你用你自己设定的类去调用NSSting的一些方法时,会存在无法实现的问题,这是为什么呢. 1.类簇里有很多私有的 ...

  5. 虚函数列表: 取出方法 // 虚函数工作原理和(虚)继承类的内存占用大小计算 32位机器上 sizeof(void *) // 4byte

    #include <iostream> using namespace std; class A { public: A(){} virtual void geta(){ cout < ...

  6. 使用Json.Net处理json序列化和反序列化接口或继承类

    以前一直没有怎么关注过Newtonsoft的Json.Net这个第三方的.NET Json框架,主要是我以前在开发项目的时候大多数使用的都是.NET自带的Json序列化类JavaScriptSeria ...

  7. java 继承类与接口问题

    java 先extends 继承类,再implements 继承接口 public class DataBase extends ClassBase implements Ijiekou { }// ...

  8. 【整理】C++虚函数及其继承、虚继承类大小

    参考文章: http://blog.chinaunix.net/uid-25132162-id-1564955.html http://blog.csdn.net/haoel/article/deta ...

  9. QEvent整理归纳:140种类型,29个继承类,7个函数,3种事件来源

    140种事件类型: QEvent::None QEvent::AccessibilityDescription QEvent::AccessibilityHelp QEvent::Accessibil ...

随机推荐

  1. 【百度之星2014~复赛 解题报告~正解】The Query on the Tree

    声明 笔者最近意外的发现 笔者的个人网站http://tiankonguse.com/ 的很多文章被其它网站转载,但是转载时未声明文章来源或参考自 http://tiankonguse.com/ 网站 ...

  2. Dell解决黑苹果网卡(BCM94352ZAE/DW1560)怎么都打不开WiFi

    Dell解决黑苹果网卡(BCM94352ZAE/DW1560)怎么都打不开WiFi 2017年10月20日17:41:00 by SemiconductorKING 本来觉得驱动这个网卡不是个问题,以 ...

  3. Layer UI 模块化的用法(转)

    此文章适合入门的同学查看,之前因为项目的原因,在网上找了一套Layer UI做的后台管理系统模板,完全不懂LayUI里面的JS用法,看了官方文档和其它资料后才明白怎么去实现模块化这个例子,但是还是感觉 ...

  4. Windows 10 搭建Hadoop平台

    一.环境配置 JDK:1.8. Hadoop下载地址(我选择的是2.7.6版本):https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common/ ...

  5. 启动memcache 服务器端

    # memcached -d -m 10 -u root -p 11211 -c 256 -P /tmp/memcached.pid -d选项是启动一个守护进程, -m是分配给Memcache使用的内 ...

  6. influxdb 端口、数据结构、写数据

    InfluxDB 是一个开源,分布式,时间序列,事件,可度量和无外部依赖的数据库. InfluxDB有三大特性: Time Series (时间序列):你可以使用与时间有关的相关函数(如最大,最小,求 ...

  7. SZU1

    CodeForces 518A 字符串进位.. #include <iostream> #include <string> #include <cstring> # ...

  8. ccf-201709-2 公共钥匙盒

    问题描述 有一个学校的老师共用N个教室,按照规定,所有的钥匙都必须放在公共钥匙盒里,老师不能带钥匙回家.每次老师上课前,都从公共钥匙盒里找到自己上课的教室的钥匙去开门,上完课后,再将钥匙放回到钥匙盒中 ...

  9. 洛谷11月月赛题解(A-C)

    心路历程 辣鸡T3卡我1.5h题意,要不是最后nlh跟我解释了一下大样例估计这次是真凉透了.. A P4994 终于结束的起点 打出暴力来发现跑的过最大数据?? 保险起见还是去oeis了一波,然后被告 ...

  10. 【代码笔记】Java常识性基础补充(二)——数组、ArrayList集合、ASCII编码、 eclipse基础操作、eclipse调试、eclipse项目导入、eclipse快捷键

    1.0 如何定义数组以及访问数组中的元素,如下所示.ArrayDemo01.java public class ArrayDemo01 { public static void main(String ...