zoukankan      html  css  js  c++  java
  • 《Entity Framework 6 Recipes》中文翻译系列 (33) ------ 第六章 继承与建模高级应用之TPH与TPT (2)

    翻译的初衷以及为什么选择《Entity Framework 6 Recipes》来学习,请看本系列开篇

    6-8  嵌套的TPH建模

    问题

      你想使用超过一层的TPH继承映射为一张表建模。

    解决方案

      假设你有一张员工(Employee)表,它包含各种类型的员工,比如,钟点工,雇员。如图6-10所示。

    图6-10 包含各种类型的员工表

      Employee表包含钟点工,雇员,提成员工,这是雇员下面的一个子类型。按下面的步骤,使用派生类型HourlyEmployee,SalariedEmployee和SalariedEmployee的子类CommissionedEmployee为这张表建模。

        1、在你的项目中创建一个继承自DbContext的上下文对象Recipe8Context;

        2、创建POCO实体类 Employee、HourlyEmployee、SalariedEmployee和CommissionedEmployee,如代码清单6-23所示;

    代码清单6-23.POCO实体类mployee, HourlyEmployee, SalariedEmployee和CommissionedEmployee

     1  public abstract class Employee
     2     {
     3         public int EmployeeId { get; set; }
     4         public string Name { get; set; }
     5     }
     6 
     7     public class SalariedEmployee : Employee
     8     {
     9         public decimal? Salary { get; set; }
    10     }
    11 
    12     public class CommissionedEmployee : SalariedEmployee
    13     {
    14         public decimal? Commission { get; set; }
    15     }
    16 
    17     public class HourlyEmployee : Employee
    18     {
    19         public decimal? Rate { get; set; }
    20         public decimal? Hours { get; set; }
    21     }
    22 }

        3、在上下文对象中添加一个类型为DbSet<Employee>的属性;

        4、在上下文对象中重写OnModelCreating方法,配置TPH中每个派生类的鉴别值,如代码清单6-24所示;

    代码清单6-24. 重写OnModelCreating方法,配置TPH中每个派生类的鉴别值

     1   protected override void OnModelCreating(DbModelBuilder modelBuilder)
     2         {
     3             base.OnModelCreating(modelBuilder);
     4 
     5             modelBuilder.Entity<Employee>()
     6                         .HasKey(e => e.EmployeeId)
     7                         .Property(e => e.EmployeeId)
     8                         .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
     9 
    10             modelBuilder.Entity<Employee>()
    11                         .Map<HourlyEmployee>(m => m.Requires("EmployeeType").HasValue("hourly"))
    12                         .Map<SalariedEmployee>(m => m.Requires("EmployeeType").HasValue("salaried"))
    13                         .Map<CommissionedEmployee>(m => m.Requires("EmployeeType").HasValue("commissioned"))
    14                         .ToTable("Employee", "Chapter6");
    15         }

    原理

      TPH继承映射是一种灵活的建模技术。继承树的深度和广度可以进行合理地扩展,映射也容易实现。这种方法有效率,是因为它没有引入额外的表,不涉及join连接。

      使用Code-First来实现TPH简单明了,因为面向对象的继承,层次自然。

      代码清单6-25演示了从模型中插入和获取。

    代码清单6-25.插入并获取Employee的派生类型

     1  using (var context = new Recipe8Context())
     2             {
     3                 var hourly = new HourlyEmployee
     4                 {
     5                     Name = "Will Smith",
     6                     Hours = (decimal)39,
     7                     Rate = 7.75M
     8                 };
     9                 var salaried = new SalariedEmployee
    10                 {
    11                     Name = "JoAnn Woodland",
    12                     Salary = 65400M
    13                 };
    14                 var commissioned = new CommissionedEmployee
    15                 {
    16                     Name = "Joel Clark",
    17                     Salary = 32500M,
    18                     Commission = 20M
    19                 };
    20                 context.Employees.Add(hourly);
    21                 context.Employees.Add(salaried);
    22                 context.Employees.Add(commissioned);
    23                 context.SaveChanges();
    24             }
    25 
    26             using (var context = new Recipe8Context())
    27             {
    28                 Console.WriteLine("All Employees");
    29                 Console.WriteLine("=============");
    30                 foreach (var emp in context.Employees)
    31                 {
    32                     if (emp is HourlyEmployee)
    33                         Console.WriteLine("{0} Hours = {1}, Rate = {2}/hour",
    34                                            emp.Name,
    35                                            ((HourlyEmployee)emp).Hours.Value.ToString(),
    36                                            ((HourlyEmployee)emp).Rate.Value.ToString("C"));
    37                     else if (emp is CommissionedEmployee)
    38                         Console.WriteLine("{0} Salary = {1}, Commission = {2}%",
    39                                     emp.Name,
    40                                     ((CommissionedEmployee)emp).Salary.Value.ToString("C"),
    41                                     ((CommissionedEmployee)emp).Commission.ToString());
    42                     else if (emp is SalariedEmployee)
    43                         Console.WriteLine("{0} Salary = {1}", emp.Name,
    44                                     ((SalariedEmployee)emp).Salary.Value.ToString("C"));
    45                 }
    46             }

    代码清单6-25的输出如下:

    All Employees
    =============
    Will Smith Hours = 39.00, Rate = $7.75/hour
    JoAnn Woodland Salary = $65,400.00
    Joel Clark Salary = $32,500.00, Commission = 20.00%

    6-9  在TPT继承映射中应用条件

    问题

      你想在TPT继承映射中应用条件。

    解决方案

      假设你有两张如图6-11所示的表。Toy(玩具)表描述一个公司的玩具产品,大部份手工制作的玩具用于销售,一部分捐献给慈善机构。在制作过程中,有些玩具可能会损坏。损坏的玩具将被翻新。一个质检员决定翻新玩具最终的质量。

    图6-11 玩具(Toy)表和翻新玩具(Refurbished)表间的一对一的关系

      为这家公司生成报表的应用,不需要访问用于捐献的玩具。按下面的步骤,使用TPT继承映射为Toy和RefurbishedToy表建模,同时过滤掉用于捐献的手工玩具:

        1、在你的项目中添加一个ADO.NET Entity Data Model(ADO.NET实体数据模型),并导入表Toy和ReferbishedToy;

        2、删除实体Toy与RefurbishedToy之间的关联;

        3、右键Toy实体,选择Add(增加) ➤Inheritance(继承)。选择Toy作为基类,RefurbishedToy作为派生类;

        4、从实体RefurbishedToy中删除属性ToyId;

        5、选择实体RefurbishedToy,并查看Mapping Details window(映射详细信息窗口),将ToyId列映射到ToyId属性。这个值将来至基类Toy;

        6、从Toy实体中删除标量属性ForDonatinOnly;

        7、选择实体Toy,并查看Mapping Details window(映射详细信息窗口),使用Add a Talbe or View(添加表或视图)来映射Toy实体到实体表。添加一个条件当ForDonationOnly=0;

      最终的模型如图6-12所示。

    图6-12 Toy实体和它的派生类型RefurbishedToy实体的概念模型

    原理

       通过在基类中应用一个条件,我们限制RefurbishedToy实例为非捐献玩具。这种方法在如下的情况下非常有用,用一张单独的表来实现继承类型映射,同时使用一个固定的条件来过滤这个继承结构。

      代码清单6-26 演示了从这个模型中插入和获取数据。

    代码清单6-26. 从模型中插入和获取数据

     1  using (var context = new Recipe9Context())
     2             {
     3                 context.Database.ExecuteSqlCommand(@"insert into chapter6.toy
     4              (Name,ForDonationOnly) values ('RagDoll',1)");
     5                 var toy = new Toy { Name = "Fuzzy Bear", Price = 9.97M };
     6                 var refurb = new RefurbishedToy
     7                 {
     8                     Name = "Derby Car",
     9                     Price = 19.99M,
    10                     Quality = "Ok to sell"
    11                 };
    12                 context.Toys.Add(toy);
    13                 context.Toys.Add(refurb);
    14                 context.SaveChanges();
    15             }
    16 
    17             using (var context = new Recipe9Context())
    18             {
    19                 Console.WriteLine("All Toys");
    20                 Console.WriteLine("========");
    21                 foreach (var toy in context.Toys)
    22                 {
    23                     Console.WriteLine("{0}", toy.Name);
    24                 }
    25                 Console.WriteLine("
    Refurbished Toys");
    26                 foreach (var toy in context.Toys.OfType<RefurbishedToy>())
    27                 {
    28                     Console.WriteLine("{0}, Price = {1}, Quality = {2}", toy.Name,
    29                                        toy.Price, ((RefurbishedToy)toy).Quality);
    30                 }
    31             }

    代码清单6-26的输出如下:

    All Toys
    ========
    Fuzzy Bear
    Derby Car
    Refurbished Toys
    Derby Car, Price = 19.99, Quality = Ok to sell

    实体框架交流QQ群:  458326058,欢迎有兴趣的朋友加入一起交流

    谢谢大家的持续关注,我的博客地址:http://www.cnblogs.com/VolcanoCloud/

  • 相关阅读:
    C#获取windos 登录用户信息
    像我这样的人
    只道情深,奈何缘浅(雪之轻裳搜集)
    如果我死了,还剩下什么(雪之轻裳)
    嫁给爱情 还是嫁给现实(搜集)
    排名前 16 的 Java 工具类
    java 获取当前屏幕截图
    转:零售数据观(一):如何花30分钟成为一个标签设计“达人”
    转:数据指标系列:电商数据分析指标体系总结V1.0
    转:领域模型中的实体类分为四种类型:VO、DTO、DO、PO
  • 原文地址:https://www.cnblogs.com/VolcanoCloud/p/4537439.html
Copyright © 2011-2022 走看看