EntityFramework Code-First 简易教程(四)-------继承策略

在前篇CodeFirst类型约定中,我们在数据库中为每一个模型类创建一个表,但是有个问题,我们可以设计出带继承关系的模型类,即面向对象编程既有“has a”(表示类继承)也有“is a”(表示类包含)关系,但是SQL的基础关系模型在表与表中仅支持"has a"关系,SQL数据库管理系统不支持继承类型。所以,怎样用关系型数据库来映射面向对象模型呢?

Code-First中有下面三种不同的方法来表示一个继承的层次结构:

  • Table per Hierarchy (TPH): 这种方法建议用一张表来表示继承层次结构,即这张表里包含了两个有继承关系类的鉴别列。看如下代码

public abstract class BillingDetail
{
    public int BillingDetailId { get; set; }
    public string Owner { get; set; }
    public string Number { get; set; }
}

public class BankAccount : BillingDetail
{
    public string BankName { get; set; }
    public string Swift { get; set; }
}

public class CreditCard : BillingDetail
{
    public int CardType { get; set; }
    public string ExpiryMonth { get; set; }
    public string ExpiryYear { get; set; }
}

public class InheritanceMappingContext : DbContext
{
    public DbSet<BillingDetail> BillingDetails { get; set; }
}

BankAccount类和CreaditCard类都继承于BillingDetail,在数据库中会生成如下表:

在EF中这是默认的继承映射层级结构

  • Table per Type (TPT): 这个方法建议为每一个模型类写一个分离的表。如下图所示:

代码如下:

public abstract class BillingDetail
{
    public int BillingDetailId { get; set; }
    public string Owner { get; set; }
    public string Number { get; set; }
}

[Table("BankAccounts")]
public class BankAccount : BillingDetail
{
    public string BankName { get; set; }
    public string Swift { get; set; }
}

[Table("CreditCards")]
public class CreditCard : BillingDetail
{
    public int CardType { get; set; }
    public string ExpiryMonth { get; set; }
    public string ExpiryYear { get; set; }
}

public class InheritanceMappingContext : DbContext
{
    public DbSet<BillingDetail> BillingDetails { get; set; }
}

  • Table per Concrete class (TPC): 这个方法建议除了抽象类,一个实体类对应一个表。所以,如果有多个实体类继承于抽象类,抽象属性将会成为每个实体类对应的表的一部分。如下图:

代码:

public abstract class BillingDetail
{
    public int BillingDetailId { get; set; }
    public string Owner { get; set; }
    public string Number { get; set; }
}

public class BankAccount : BillingDetail
{
    public string BankName { get; set; }
    public string Swift { get; set; }
}

public class CreditCard : BillingDetail
{
    public int CardType { get; set; }
    public string ExpiryMonth { get; set; }
    public string ExpiryYear { get; set; }
}

public class InheritanceMappingContext : DbContext
{
    public DbSet<BillingDetail> BillingDetails { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<BankAccount>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("BankAccounts");
        });

        modelBuilder.Entity<CreditCard>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("CreditCards");
        });
    }
}

上面说的比较简单,如果想要了解更多详细信息,点击下面的是三个链接:

  1. Inheritance with EF Code First: Table per Hierarchy (TPH)
  2. Inheritance with EF Code First: Table per Type (TPT)
  3. Inheritance with EF Code First: Table per Concrete class (TPC)

总结:这一节我也看得一知半解,如果有大神肯指点迷津,不胜感激。

时间: 2024-08-07 19:09:41

EntityFramework Code-First 简易教程(四)-------继承策略的相关文章

WebGL简易教程(四):颜色

目录 1. 概述 2. 示例:绘制三角形 1) 数据的组织 2) varying变量 3. 结果 4. 理解 1) 图形装配和光栅化 2) 内插过程 5. 参考 1. 概述 在上一篇教程<WebGL简易教程(三):绘制一个三角形(缓冲区对象)>中,通过使用缓冲区对象(buffer object)来向顶点着色器传送数据.那么,如果这些数据(与顶点相关的数据,如法向量.颜色等)需要继续传送到片元着色器该怎么办呢? 例如这里给三角形的每个顶点赋予不同的颜色,绘制一个彩色的三角形.这个时候就需要用到之

Android实战简易教程-第四十枪(窃听风云之短信监听)

近期在做监听验证码短信自己主动填入的功能,无意间想到了一个短信监听的办法. 免责声明:短信监听本身是一种违法行为,这里仅仅是技术描写叙述.请大家学习技术就可以.(哈哈) 本实例是基于bmob提供的后台服务,将监听到的短信自己主动上传到bmob数据库中. 一.代码实现: 1.首先实现javabean对象. package com.example.messagecut; import cn.bmob.v3.BmobObject; public class MsgContent extends Bmo

EntityFramework 5.0 CodeFirst 教程01-搭建环境和快速上手

----------------------------目录------------------------------ EntityFramework 5.0 CodeFirst 教程01-搭建环境和快速上手 ----------------------------目录------------------------------ 网上关于EntityFramework 5.0的教程很多,但是大多数都是代码整理不清晰,有些甚至是拷贝,代码丢失等问题,本人最近也有一个项目是用到EntityFram

文件上传利器SWFUpload入门简易教程

凡做过网站开发的都应该知道表单file的确鸡肋. Ajax解决了不刷新页面提交表单,但是却没有解决文件上传不刷新页面,当然也有其它技术让不刷新页面而提交文件,该技术主要是利用隐藏的iFrame, 较Ajax要麻烦许多,而且其提交方式依然在底层是使用的表单file,这里我们不详谈.而且如果是提交较小的文件,我们能接受,如果提交的文件较大,我 们便要忍受很长的等待时间,而浏览器却没有任何提示,我们也没有办法知道文件上传的进度… 但是现在,网上出现了一个名为SWFUpload的上传组件,该组件利用Fl

Ocelot简易教程(五)之集成IdentityServer认证以及授权

原文:Ocelot简易教程(五)之集成IdentityServer认证以及授权 Ocelot简易教程目录 Ocelot简易教程(一)之Ocelot是什么 Ocelot简易教程(二)之快速开始1 Ocelot简易教程(二)之快速开始2 Ocelot简易教程(三)之主要特性及路由详解 Ocelot简易教程(四)之请求聚合以及服务发现 Ocelot简易教程(五)之集成IdentityServer认证以及授权 Ocelot简易教程(六)之重写配置文件存储方式并优化响应数据 Ocelot简易教程(七)之配

Junit 4 Tutorials(Junit 4 教程) 四、Junit4 参数化测试

Junit 4 参数化测试 允许通过变化范围的参数值来测试方法.参数擦测试可以通过以下简单的步骤实现: 对测试类添加注解 @RunWith(Parameterized.class) 将需要使用变化范围参数值测试的参数定义为私有变量 使用上一步骤声明的私有变量作为入参,创建构造函数 .创建一个使用@Parameters注解的公共静态方法,它将需要测试的各种变量值通过集合的形式返回. 使用定义的私有变量定义测试方法 Junit 4 参数化测试样例 EvenNumberChecker.java 校验输

移动开发之【微信小程序】的原理与权限问题以及相关的简易教程

这几天圈子里到处都在传播着这样一个东西,微信公众平台提供了一种新的开放能力,开发者可以快速开发一个小程序,取名曰:微信公众平台-小程序 据说取代移动开发安卓和苹果,那这个东东究竟是干吗用的?但很多人觉得是网页版应用. 有的人很鸡冻,但是--最后文章会提及具体的权限开放问题,所以,还是保持一颗冷静的?比较好. 那我们先来看看组件和API开放了哪些服务: 视图容器:视图(View).滚动视图.Swiper 基础内容:图标.文本.进度条 表单组件:按钮.表单等等 操作反馈 导航 媒体组建:音频.图片.

Android实战简易教程-第五十一枪(ListView实现子控件的动态显示和隐藏、checkbox全选和反选)

前段时间写过一篇文章:Android实战简易教程-第四十七枪(ListView多选-实现点餐系统)有的同学留言建议,可不可以动态控制checkbox的显示和全选反选功能,我研究了一下,发现实现也比较容易,特写下此篇文章.学习就是要有发散思维,要举一反三,大家也可以根据我的实例进行改编,添加和删除一些功能,这样可以提高你对知识的认知!下面我们看一下代码: 1.main.xml: <?xml version="1.0" encoding="utf-8"?>

CRL快速开发框架系列教程四(删除数据)

本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框架系列教程四(删除数据) CRL快速开发框架系列教程五(使用缓存) CRL快速开发框架系列教程六(分布式缓存解决方案) CRL快速开发框架系列教程七(使用事务) CRL快速开发框架系列教程八(使用CRL.Package) CRL快速开发框架系列教程九(导入/导出数据) CRL快速开发框架系列教程十(

Laravel教程 四:数据库和Eloquent

Laravel教程 四:数据库和Eloquent 此文章为原创文章,未经同意,禁止转载. Eloquent Database 上一篇写了一些Laravel Blade的基本用法和给视图传递变量的几种方式, 这一节我们来说说跟数据库打交道的数据库配置和Laravel强大的Eloquent. Laravel的数据库配置 本部分内容为下节做准备 Laravel的配置文件都是在项目目录的config/文件夹之下,这里也就是在blog/config文件夹之下,你可以打开这个文件夹看看,你面有很多配置文件: