一、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. 通过反射获取及调用方法(Method)

    1.获取方法使用反射获取某一个类中的方法,步骤:①找到获取方法所在类的字节码对象②找到需要被获取的方法 Class类中常用方法: public Method[] getMethods():获取包括自身 ...

  2. PHP正则表达式(转载)

    这个星期要攻破PHP正则表达式   正则表达式定义 正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串.将匹配的子串做替换或者从某个串中取 ...

  3. linux diff(differential) 命令

    功能说明:比较文件的差异. 语法:diff [OPTION]... FILES 实例: diff -ur temp1 temp2 diff -ur temp1 temp2 > temp.diff ...

  4. js运动缓动效果

    http://www.cnblogs.com/hongru/archive/2012/03/16/2394332.html  转分享地址

  5. 阿里云服务器docker搞定镜像

    docker的安装可以看前面的文章 这里我的docker已经安装完成了,该搞镜像了:这里的镜像用的是我以前自己搞的,虽然镜像有点大,但是胜在自己搞的,熟悉(熟悉不熟悉鬼知道) 我的镜像放在了阿里云容器 ...

  6. sql server存储过程中SELECT 与 SET 对变量赋值的区别 转自Theo

    SQL Server 中对已经定义的变量赋值的方式用两种,分别是 SET 和 SELECT. 对于这两种方式的区别,SQL Server 联机丛书中已经有详细的说明,但很多时候我们 并没有注意,其实这 ...

  7. PHP学习6——常用函数

    主要内容: 字符串处理函数 时间和日期处理函数 字符串处理函数 echo输出字符串 print输出字符串,带返回值1 print.php <?php var_dump(print("有 ...

  8. 智能提示含查询多列(html+JS+handler+ HttpRemoting)二、Remoting代码

    /// <summary> /// 智能查询类型 /// </summary> public enum QueryType : byte { /// <summary&g ...

  9. PHP开发框架CodeIgniter

    CodeIgniter 是一套给 PHP 网站开发者使用的应用程序开发框架和工具包. 通过下面四步来安装 CodeIgniter: 解压缩安装包: 将 CodeIgniter 文件夹及里面的文件上传到 ...

  10. SQL Join 语句

    SQL Join 语句 SQL 中每一种连接操作都包括一个连接类型和连接条件. 连接类型 决定了如何处理连接条件不匹配的记录. 连接类型 返回结果 inner join 只包含左右表中满足连接条件的记 ...