一、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. Spark on YARN简介与运行wordcount(master、slave1和slave2)(博主推荐)

    前期博客 Spark on YARN模式的安装(spark-1.6.1-bin-hadoop2.6.tgz +hadoop-2.6.0.tar.gz)(master.slave1和slave2)(博主 ...

  2. jenkins启动脚本

    [root@localhost system]# cat /etc/init.d/jenkins #!/bin/sh # # SUSE system statup script for Jenkins ...

  3. .netCore2.0 WebApi 传递form表单

    随着it的技术发展,目前越来越多的项目采用前后端分离的开发模式,通过webapi提供接口数据来进行交互 最近项目用的是.netCore WebApi,在最近的项目使用中发现一些问题,进行记录.个人简介 ...

  4. SpringBoot 开启debug

    项目基于gradle ,今天想断点debug一下springboot,查阅资料后,纪录一下步骤. 创建Remote 创建gradle.properities 在当前项目下创建gradle.proper ...

  5. 二:Nexus知识

    Nexus访问 Http://localhost:8080/nexus Nexus登陆 用户:admin 密码:admin123 Nexus仓库 nexus的仓库类型分为以下四种: group: 仓库 ...

  6. JSON 转 VO

    需求 将获取的json数据直接转为vo 解决 利用net.sf.json.JSONObject的toBean() 确保json中的key值和vo中的字段名称一致 JSONObject jsonObje ...

  7. Linux 创建python虚拟环境

    使用virtualenv包管理工具来管理虚拟环境 1.安装virtualenv 不知啥原因,第一次安装超时失败,第二次下载到30%超时失败,第三次才安装成功 2.创建虚拟环境 只有python2.7及 ...

  8. lintcode题目记录4

    Russian Doll Envelopes    Largest Divisible Subset     Two Sum - Input array is sorted Russian Doll ...

  9. *p++、*++p、(*p)++区别

    关于数组指针的谜题 假设 p 是指向数组 arr 中第 n 个元素的指针,那么 *p++.*++p.(*p)++ 分别是什么意思呢? *p++ 等价于 *(p++),表示先取得第 n 个元素的值,再将 ...

  10. js 显示 base64编码 的二进制流 图片

    Data URI scheme.Data URI scheme是在RFC2397中定义的,目的是将一些小的数据,直接嵌入到网页中,从而不用再从外部文件载入.比如上面那串字符,其实是一张小图片,将这些字 ...