Entity Framework映射TPH、TPT、TPC与继承类

目录
  • 一、TPH
    • 1、默认行为
    • 2、Fluent API修改默认行为
  • 二、TPT
    • 1、默认行为
    • 2、Fluent API修改默认行为
  • 三、TPC
    • 1、默认行为
    • 2、Fluent API修改默认行为
  • 四、实体拆分
  • 五、表拆分
  • 六、将类指定为复杂类型
    • 1、指定方法:
    • 2、配置复杂类型的属性
  • 七、DataBase初始化
    • 1、调用Database.SetInitializer方法:
    • 2、通过配置文件更灵活的指定数据库初始化的方式:
    • 3、自定义数据库初始化类

一、TPH

Table Per Hierarchy (默认,每个层次一个表)

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

1、默认行为

只建立一个表,把基类和子类中的所有属性都映射为表中的列。 
为基类和所有子类共建立一个表,基类和子类中的所有属性都映射为表中的一个列。

默认在这个表中建立一个叫做Discriminator的列,类型是nvarchar,长度是128。在存储基类或子类的时候,把类名作为Discriminator列的值。

2、Fluent API修改默认行为

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

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

二、TPT

Table Per Type(每个类各一个表)

1、默认行为

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

2、Fluent API修改默认行为

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

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

三、TPC

Table Per ConCrete Type(每个具体类型各一个表)

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

1、默认行为

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

2、Fluent API修改默认行为

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

注意:因为属于 TPC 继承层次结构的表并不使用同一个主键, 关闭主键属性的标识,避免为不同子表插入重复的实体键。

modelBuilder.Entity<Course>()
     .Property(c => c.CourseID)
     .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

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]
public Details details;

或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(100);
            Property(a => a.ZipCode).HasColumnName("ZipCode").HasMaxLength(6);
         }
     }

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

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

七、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="DatabaseInitializerForTypeOrderSystemContext" 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 = 5600, NetPrice = 4300 });
            context.ProductCatalogs.Add(new ProductCatalog { CatalogName = "DELL E6420", Manufactory = "DELL", ListPrice = 7000, NetPrice = 5400 });
        }
    } 

Database.SetInitializer(new DropCreateOrderDatabaseWithSeedValueAlways());

到此这篇关于Entity Framework映射TPH、TPT、TPC与继承类的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Entity Framework配置关系

    目录 一.Has方法与With方法 1.Has方法: 2.With方法: 二.一对一关系: 1.DataAnnotations数据标注的方式 2.Fluent API方式 (1)1:0..1关系 (2)1:1 关系 三.一对多关系: 1.DataAnnotations方式 2.更改外键的nullable属性和外键的名字 1.使用Data Annotations指定外键: 2.用Fluent API指定外键: 3.对同一实体多个引用的情况 4.级联删除 四.多对多关系 指定表名 一.Has方法与W

  • Entity Framework主从表的增删改

    目录 一.添加数据 1.在主表中添加从表数据 2.添加主表的同时添加从表数据 3.添加从表的同时添加主表数据 二.修改关联 1.修改从表的外键 2.从表与主表脱离关系 三.删除关联数据 1.删除主表的同时删除相关联的从表数据(级联删除) 2.普通删除 一.添加数据 1.在主表中添加从表数据 在景点的住宿集合(Lodgings)中增加一个度假区(Resort) var dest = (from d in context.Destinations where d.Name == "Bali"

  • Entity Framework主从表数据加载方式

    一.延迟加载:LazyLoading 使用延迟加载,关联的实体必须标注为virtual. 本例是标注Destination类里的Lodgings为virtual.因为先发sql去查询主键对象,然后根据主键id去从表里查相关联的数据. private static void TestLazyLoading() { using (var context = new CodeFirst.DataAccess.BreakAwayContext()) { var canyon = (from d in c

  • Entity Framework模型优先与实体对象查询

    目录 一.概念: 1.EF6 可实现的功能: 二.安装Entity Framework6 1.VS2019 Installer安装“Entity Framework6 工具” 2.通过Nuget安装“Entity Framework”: 三.新建ObjectContext 和EntityObject 1.“根据模型生成的数据库”的设计器功能实现ModelFirst. 四.实体对象查询:linq to Entities 1.使用lambda表达式查询 2.执行存储过程(通过“添加”-----”函数

  • Entity Framework代码优先(Code First)模式

    目录 一.Code First 代码优先 二.创建或生成Model代码 1.从数据库生成Model代码 2.手工创建Model代码 三.配置文件 四.操作 1.添加单个实体,Add 2.修改 3.删除,Remove 五.查询 1.Load(): 2.ToList(): 3.Find(): 4.Single().SingleOrDefault().First()等: 六.直接执行SQL语句 1.在实体上运行SQL命令, 2.在Database属性上运行SQL命令 一.Code First 代码优先

  • Entity Framework使用ObjectContext类

    目录 一.ObjectContext对象上下文 1.ObjectContext和DbContext的对比 2.ObjectContext类的实例封装的内容 3.类的结构: 二.实体对象查询:linq to Entities 1.AddObject :添加实体 2.DeleteObject: 删除实体 3.Detach: 分离实体 4.修改实体 5.保存到数据库 三.对象状态管理 1.ObjectStateEntry对象状态实体 2.ObjectStateManager对象状态管理器 五.Obje

  • Entity Framework映射TPH、TPT、TPC与继承类

    目录 一.TPH 1.默认行为 2.Fluent API修改默认行为 二.TPT 1.默认行为 2.Fluent API修改默认行为 三.TPC 1.默认行为 2.Fluent API修改默认行为 四.实体拆分 五.表拆分 六.将类指定为复杂类型 1.指定方法: 2.配置复杂类型的属性 七.DataBase初始化 1.调用Database.SetInitializer方法: 2.通过配置文件更灵活的指定数据库初始化的方式: 3.自定义数据库初始化类 一.TPH Table Per Hierarc

  • Entity Framework使用Code First的实体继承模式

    目录 一.TPT继承模式 1.Person类 2.使用数据迁移创建数据库 3.填充数据 二.TPH模式 1.创建有继承关系的实体类 2.创建数据上下文 3.使用数据迁移创建数据库 4.不使用默认生成的区别多张表的类型 5.填充数据 6.查询数据 三.TPC模式 1.创建实体类 2.配置数据上下文 3.使用数据迁移生成数据库 4.填充数据 Entity Framework的Code First模式有三种实体继承模式 1.Table per Type (TPT)继承 2.Table per Clas

  • Entity Framework Core更新时间映射

    时间字段 在真实的开发中,为了跟踪数据的变化,一般会在数据表里面有CreatedTime和UpdatedTime两列.CreatedTime表示创建时间,新增一条数据的时候,会更新CreatedTime列的值.UpdatedTime表示更新时间,更新数据的同时也会更新UpdatedTime列的值,这时候就需要对应的映射来配置.我们修改Blog类,增加这两个时间字段: using System; namespace EFCore.Model { public class Blog { public

  • Entity Framework Core表名映射

    表名映射 我们知道:如果是在默认情况下,使用EFCore Code First的方式生成的表名跟数据上下文类中定义的实体属性的名称是一致的,例如: public DbSet<Blog> Bloges123 { get; set; } 这里定义的属性名称是Bloges123,那么最后数据库中生成的表名也叫Bloges123.看下面的测试. 我们首先添加迁移,每次迁移都会生成一个对应的迁移记录类,代码如下图所示: 可以看到,这里显示创建表的名称就是Bloges123.最后更新数据库,更新完成以后查

  • Entity Framework系统架构与原理介绍

    一.Entity Framework概要 Entity Framework是微软的Object Relational Mapper(对象关系映射),也就是我们平常说的ORM,它可以让应用程序开发者将关系型数据作为业务模型来使用,也消除了开发者为数据访问编写的绝大多数管道代码的需要(比如使用ADO.NET).Entity Framework提供了一个综合的.基于模型的系统,通过摆脱为所有的领域模型编写相似的数据访问代码,使得开发者创建数据访问层是如此之简单.Entity Framework的首发版

  • Entity Framework使用配置伙伴创建数据库

    在上一篇文章中讲了如何使用fluent API来创建数据表,不知道你有没有注意到一个问题.上面的OnModelCreating方法中,我们只配置了一个类Product,也许代码不是很多,但也不算很少,如果我们有1000个类怎么办?都写在这一个方法中肯定不好维护.EF提供了另一种方式来解决这个问题,那就是为每个实体类单独创建一个配置类.然后在OnModelCreating方法中调用这些配置伙伴类. 创建Product实体类: using System; using System.Collectio

  • Entity Framework使用DbModelBuilder API创建表结构

    DbContext类有一个OnModelCreating方法,它用于流利地配置领域类到数据库模式的映射.下面我们以fluent API的方式来定义映射.首先,先将Product类注释掉,重新编写该类,重新编写后的Product类: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EFFluent

  • Entity Framework实现数据迁移

    一.合并和迁移 1.合并 合并是指“新的实体模型映射到数据库中,更新其结构”,例如:新增了实体类,表现在数据库中就是新增加实体类对应的数据表.删除了实体类,表现在数据库中就是删除了实体类对应的数据表.在一个已经存在的实体类中增加属性,表现在数据库中就是在实体类对应的数据表中新增加字段.在一个已经存在的实体类中删除属性,表现在数据库中就是在实体类对应的数据表中删除字段.修改一个已经存在的实体类中属性的名称或类型,表现在数据库中就是修改实体类对应的数据表中字段的名称或类型. 2.迁移 迁移是指“在更

  • Entity Framework使用DataBase First模式实现增删改查

    一.新建控制台应用程序,然后右键->添加新建项,选择数据里面的实体数据模型: 然后点击添加 二.选择来自数据库的EF设计器,并点击下一步 三.在实体数据模型向导界面选择要使用的数据连接,或者点击新建连接按钮创建新的连接,这里选择已有的连接,并点击下一步: 四.选择实体框架6.0,点击下一步: 五.选择要操作的表,并点击完成: 六.查看生成的项目结构 自动添加了EntityFramework的引用.同时会在项目的根目录下面生成一个package文件夹: package文件夹里面存放的是与Entit

随机推荐