EF中的TPH、TPT、TPC

1. Table Per Hierarchy(TPH):只建立一个表,把基类和子类中的所有属性都映射为表中的列
2. Table Per Type(TPT):为基类和每个子类建立一个表,每个与子类对应的表中只包含子类特有的属性对应的列
3. Table Per Concrete(TPC):为每个子类建立一个表,每个与子类对应的表中包含基类的属性对应的列和子类特有属性对应的列

以上摘自:传送阵

TPH

举例如下:

1  public class Resort : Lodging
2     {
3         public string Entertainment { get; set; }
4
5         public string Activities { get; set; }
6
7     }

 1 namespace MSDNBlog
 2 {
 3     public class MyContext:DbContext
 4     {
 5         public MyContext()
 6             : base("DefaultConnection")
 7         {
 8
 9         }
10         public DbSet<Lodging> Lodgings { get; set; }
11
12         protected override void OnModelCreating(DbModelBuilder modelBuilder)
13         {
14             modelBuilder.Entity<Lodging>()
15                 .Map<Lodging>(l => l.Requires("From").HasValue("Loding"))
16                 .Map<Resort>(r => r.Requires("From").HasValue("resot"));
17             base.OnModelCreating(modelBuilder);
18         }
19
20     }
21
22     public class Lodging
23     {
24         public int LodgingId { get; set; }
25         public string Name { get; set; }
26         public string Owner { get; set; }
27     }
28
29     public class Resort : Lodging
30     {
31         public string Entertainment { get; set; }
32
33         public string Activities { get; set; }
34
35     }
36 }

生成的表结构如图:

其中 Discriminator的作用是鉴别数据是来自于基类还是子类,默认类型是nvarchar(128),对应的值为相应的类的名称

可以使用Fluent API的方式修改鉴别器的名称:

1   protected override void OnModelCreating(DbModelBuilder modelBuilder)
2         {
3             modelBuilder.Entity<Lodging>()
4                 .Map<Lodging>(l => l.Requires("From").HasValue("Loding"))
5                 .Map<Resort>(r => r.Requires("From").HasValue("resot"));
6             base.OnModelCreating(modelBuilder);
7         }

此时对应的表的结构如下图:

TPT

在TPT映射情形下,所有类型分别映射到不同的表,仅属于某个基类型或派生类型的属性存储在映射到该类型的一个表中。映射到派生类型的表还会存储一个将派生表与基表连接的外键。

1    //modelBuilder.Entity<Lodging>().ToTable("Lodings");
2             //modelBuilder.Entity<Resort>().ToTable("Restorts");
3             modelBuilder.Entity<Lodging>()
4                 .Map<Lodging>(l => l.ToTable("Lodings2"))
5                 .Map<Resort>(r=>r.ToTable("Resorts2"));
6                 

生成的表结构如下图:

当然也可以使用Data Annotation方式进行处理

  [Table("Lodging")]
    public class Lodging
    {
        public int LodgingId { get; set; }
        public string Name { get; set; }
        public string Owner { get; set; }
    }
    [Table("Resort")]
    public class Resort : Lodging
    {
        public string Entertainment { get; set; }

        public string Activities { get; set; }

    }

TPC

为每个子类建立一个表,每个子类中包含基类的属性对应的列和子类特有的属性对应的列。TPC无法使用Data Annotation配置

1   //modelBuilder.Entity<Lodging>().ToTable("Lodgings");
2             //modelBuilder.Entity<Resort>().Map(r => { r.MapInheritedProperties(); r.ToTable("Resorts"); });
3             modelBuilder.Entity<Lodging>()
4                 .Map<Resort>(r => {
5                     r.ToTable("Resorts");
6                     r.MapInheritedProperties();
7                 });

生成的表结构如下图:

时间: 2024-11-11 22:40:03

EF中的TPH、TPT、TPC的相关文章

Code First 中的 TPH TPT TPC

public class Blog { public int Id { get; set; } public DateTime Creationdate { get; set; } public string ShortDescription { get; set; } public string Title { get; set; } public string AboutTheAuthor { get; set; } } public class PictureBlog : Blog { p

EF中执行sql语句

EF原理 EF 会自动把 Where().OrderBy().Select()等这些编译成"表达式树(Expression Tree)",然后会把表达式树翻译成 SQL 语句去执行.(编译原理,AST)因此不是"把数据都取到内存中,然后使用集合的方法进行数据过滤",因此性能不会低.但是如果这个操作不能被翻译成 SQL 语句,则或者报错,或者被放到内存中操作,性能就会非常低 跟踪EF的查询Sql语句: DbContext 有一个 Database 属性,其中的 Log

EF中三大开发模式之DB First,Model First,Code First以及在Production Environment中的抉择

一:ef中的三种开发方式 1. db first... db放在第一位,在我们开发之前必须要有完整的database,实际开发中用到最多的... <1> DBset集合的单复数... db => model 2. model first... 根据model生成数据库,和我们的sqlserver的可视化类视图是一样的... 其实sqlserver也是有自己的类视图... 如果用ef来创建: <1> 生成类图.. <2> 根据模型生成数据库... 3. code f

EF中逆变和协变

EF中的增删改查: 实现步骤: 1.声明一个EF的上下文. bjhksjEntities dbContext = new bjhksjEntities(); 2.声明一个实体. HKSJ_USERS user = new HKSJ_USERS(); user.LoginName = "ssss"; user.Mail = "ssss"; user.PassWord = "ssss"; user.Plane = "ssss";

数据库事务及其EF中如何处理事务

一.基础知识 1)         使用事务级别ReadUnCommited 会产生脏读现像,意味着读取到的为UnCommited(未提交)的数据.怎么理解呢?在使用该隔离级别的事务开始后.更新了数据库某一行的数据,但是事务的工作量比较大,后续还有一大堆代码还没执行完呢.不巧的是有个哥们过来读数据了,这个时候读到的就是未提交的值,如果后继工作一切正常,也没什么影响.一旦后面的代码执行中出错,就会产生不一致的错误,适用于对事务极度自信的情况下,特点为可读不可改.关于不可改需解释一下,MS SQL中

EF中的增删改查

在上一篇中简单的介绍了一下有关EF的一些概念,都是小编的一些个人理解,懂的不多,想深入学习的可以从网上查看一些其他资料. 下面紧接着上一篇所说,来从代码上看一下EF容器是如何实现与后台数据库之间的增删改查的. 1.EF包装类 什么是EF包装类呢?举个例子,我们平时用SQL语句写增删改查时,用的都是一些Insert.Update.Delete等语句来实现增删改查,所以我们把放到EF容器的东东也要做一个标签,来指明这个东东是要添加.更新.还是要删除呢. 正如上图所示就是这么简单的操作,就完成了对数据

EF中Database.SqlQuery

本文转载:http://www.cnblogs.com/daimage/archive/2012/07/04/2575844.html EF中Database.SqlQuery<TElement> Method (String, Object[]) 可以直接执行SQL语句 但以为object[]参数和在ado.net中一样呢 开始就按ADO.NET中的 写法 sql为:update Product_Union set [email protected] where [email protect

EF中执行存储过程

SqlParameter[] parms = new SqlParameter[5]; SqlParameter parms0 = new SqlParameter("IsAll", int.Parse(parames.P1)); //生成一个参数并给参数赋值. SqlParameter parms1 = new SqlParameter("ForumId", int.Parse(parames.P2)); SqlParameter parms2 = new Sql

EF中修改对象的值的问题。。。(字段超级多的时候)

一般EF中修改单个对象的值,我是这样处理的. 如:DBEntities db=new DBEntities(); student stu = db.student.firstOrdefault(m=>m.id==id); stu.name="sb"; stu.age=11; ...... db.SaveChange(); 如果字段少的情况下,没什么问题(EF中好像还有一个修改的方法,先不管它). 如果200个字段呢?你还去一个个.属性么? 这个问题我用反射可以解决.具体方法见小弟