一、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. 浅谈flex布局

    Flex布局,俗称弹性布局,有了这个布局,咱们做的事情很多,以前那些很难实现比如说垂直居中之类都不存在了. 盒模型布局依赖于float,display,定位之类的方式来布局,这种的布局对一些特殊布局来 ...

  2. 利用rem解决移动端响应适配问题

    最近看了<从网易与淘宝的font-size思考前端设计稿与工作流>和github上的<使用Flexible实现手淘H5页面的终端适配> 以前一直用百分比的我,对移动前端的H5页 ...

  3. CSS ::Selection的使用方法

    大家都知道浏览器对选中的文本默认样式都是统一的,Windows下是一个深蓝色的背景,白字的前景,而在Mac下是一个淡蓝色背景,白色字体,就如上图所展示的一样,自从有了这个“::selection”选择 ...

  4. div+css 制作表格

    <div class="table"> <h2 class="table-caption">花名册:</h2> <di ...

  5. Java线程池——ThreadPoolExecutor的使用

    1 线程池的创建 ThreadPoolExecutor有以下四个构造方法 ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long  ...

  6. .net HttpClient的使用

    在程序用调用 Http 接口.请求 http 资源.编写 http 爬虫等的时候都需要在程序集中进行 Http 请 求.  很多人习惯的 WebClient.HttpWebRequest 在 TPL ...

  7. 在C++中实现类似Java的“synchronized”

    我只是代码的搬运工,原文参见A "synchronized" statement for C++ like in Java.其实现是通过区域锁(Scoped locking)和宏定 ...

  8. JAVA数据类型中的char类型

    1.JAVA中,char占2字节,16位.可在存放汉字 2.char赋值 char a='a'; //任意单个字符,加单引号. char a='中';//任意单个中文字,加单引号. char a=11 ...

  9. MySQL prompt命令

    修改提示符,设置后挺方便的 例如: 几个好用的参数 \d 当前数据库 \u 当前用户 \h 当前主机 更多参数可以参考mysol官方文档 参考文档:https://dev.mysql.com/doc/ ...

  10. MySQL中文问题

    -- 设置客户端显示字符集 mysql>set names utf8; -- 建表时设置表的字符集和引擎 CREATE TABLE table ( `abc` char(32) NOT NULL ...