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

6-12  TPC继承映射建模

问题

  你有两张或多张架构和数据类似的表,你想使用TPC继承映射为这些表建模。

解决方案

  假设我们有如图6-18所示的表。

图6-18 表Toyota和BMW有相似的结构,它们可以成为派生至实体Car的派生类型

  在图6-18中,表Toyota和BMW有相似的架构(Schema),并描述类似的数据。BMW表只多了额外的一列,它用一bit值来指示对应的实例是否具有避免碰撞(collision-avoidance)特性。我们想在建模中,用一个基类来持有表Toyta和BMW的公共属性。另外,我们还想表示经销商与汽车库存量之间的一对多关系。 图6-22(译注:应该是图6-19)展示的是最终的模型。

  按下面的步骤创建模型:

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

    2、右键设计器,并选择Add(新增)➤Entity(实体)。命名新实体为Car,不勾选Create Key property(创建键属性)复选框;

    3、右键实体Car,选择Properties(属性)。设置Abstract(抽象)属性为True;

    4、将实体Toyota和BMW的公共属性移动到实体Car中,可以使用Cut/Paste(剪切/粘贴)来完成移动。确保Toyota实体没有属性,BMW实体只有CollisionAvoidance实体。这两个实体将从实体Car继承公共属性;

    5、右键Car实体,选择Add(增加) ➤Inheritance(继承)。选择Car作为基类,BMW作为派生类。

    6、重复上一步的操作,选择Car作为基类,Toyota作为派生类型。

    7、右键CarDealer实体,选择Delete(删除)。当提示是否从存储模型删除CarDealer时,选择No(否);

    8、右键设计器,选择Add(增加) ➤Association(关联)。命名关联为CarDealer。在左边选择Dealer,并将多重性设置为1,在右边选择Car,并将多重性设置为多。将Car这边的导航属性命名为Dealer,将Dealer这边的导航属性命名为Cars。确保不勾选Add foreign key properties(添加外键属性);

    9、选择关联,然后查看Mapping Details window(映射详细信息窗口)。在Add a Talbe or View(添加表或视图)下面菜单中,选择CarDealer。确保DealerId属性映射到DealerId列,CarID属性映射到CarId列;

  在解决方案浏览器中右键.edmx文件,选择Open With(打开方式) ➤XML Editor(XML文本编辑器),使用代码清单6-3中的更改为实体BMW和Toyota编辑映射节.

代码清单6-35. 映射实体BMW和Toyota到表

     <EntitySetMapping Name="Cars">
<EntityTypeMapping TypeName="IsTypeOf(Apress.EF6Recipes.BeyondModelingBasics.Recipe12.BMW)">
<MappingFragment StoreEntitySet="BMW">
<ScalarProperty Name="CollisionAvoidance"
ColumnName="CollisionAvoidance" />
<ScalarProperty Name="CarId" ColumnName="CarId"/>
<ScalarProperty Name="Model" ColumnName="Model"/>
<ScalarProperty Name="Year" ColumnName="Year"/>
<ScalarProperty Name="Color" ColumnName="Color"/>
</MappingFragment>
</EntityTypeMapping>
<EntityTypeMapping TypeName="IsTypeOf(Apress.EF6Recipes.BeyondModelingBasics.Recipe12.Toyota)">
<MappingFragment StoreEntitySet="Toyota">
<ScalarProperty Name="CarId" ColumnName="CarId"/>
<ScalarProperty Name="Model" ColumnName="Model"/>
<ScalarProperty Name="Year" ColumnName="Year"/>
<ScalarProperty Name="Color" ColumnName="Color"/>
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>

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

图6-19  概念模型,它描述了派生类型BMW和Toyota在数据库表示为单独的表

原理

  TPC是一个有趣的继承模型,它允许每个派生类实体映射到单独的物理表。从实用的角度来看,表至少有一部分公共的架构。 这个公共的的架构被映射到基类,额外部分的架构映射到派生类实体。为了让TPC继承模型正常工作,实体键在整个相关表(译注:如本示例中的表Toyota和BMW)中必须唯一

  基类实体被标记为抽象类型,它不被映射到任何表。在TPC中,只有派生类型实体被映射到表

  在我们的示例中,我们标记Car实体为抽象类型,不对它进行映射。注意,在代码清单6-35的映射中,我们只映射派生类型BMW和Toyota。我们将公共属性(CarID,Model,Year和Color)移动到了基类实体。派生类只包含属于自己的独特的属性。 实例中,BMW实体的实例有一个额外的属性CollisionAvoidance。

  因为实体Toyota和BMW派生至实体Car,所以,它们变成了相同实体集Cars的一部分。这意味着,实体键必须在包含整个派生类型的实体集中唯一。因为实体被映射到不同的表,所以我有可能会碰到相同的键。为了避免这种情况的发生,我们将每张表的CarId列设置为标识列。对于BMW表,我们将主键的种子(基数)初始化为1并设置递增为2,这将会为主键CarId创建奇数值。对于Toyota表,我们将主键的种子初始化为2并设置增量为2,这将为主键CarId创建偶数值。

  当在使用TPC继承映射建模关系时,在派生中定义关系比在基类中定义更好。这是因为实体框架在运行时不知道关联的另一端是哪张物理表。当然,在我们的示例中,我们提供了一张单独的表(CarDealer),它包含了关系。这就允许我们可以在基类中映射关系到CarDealer表。

  在很多使用TPC继承映射的实际应用,最常见的也许是,处理存档数据。假设你的电子商务网站有多年的订单数据。在每年的年终,你将前面12个月的订单存档在Archive表,并为新的一年准备一张空表。你可以使用这里演示的方法,用TPC为当前和存档的订单建模。

  TPC继承映射跟别的继承映射相比,有一个特别重要的性能优势。当查询一个一派生类型时,产生针对底层数据库表的查询,没有像TPT继承映射中额外的join连接,也没有像TPH中的过滤。对于有几个派生类型的大型数据集或模型,这种性能优势显得至关重要。

  TPC继承映射的缺点是,包含对潜在重复数据的开销,和在整个相关表中确保主键唯一的复杂性。在存档场景中,数据不是重复,只是简单的分布在多张表中。在别的场景中,数据(属性)在相关表中可能会有重复。

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

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

  using (var context = new Recipe12Context())
{
var d1 = new Dealer { Name = "All Cities Toyota" };
var d2 = new Dealer { Name = "Southtown Toyota" };
var d3 = new Dealer { Name = "Luxury Auto World" };
var c1 = new Toyota
{
Model = "Camry",
Color = "Green",
Year = ,
Dealer = d1
};
var c2 = new BMW
{
Model = "310i",
Color = "Blue",
CollisionAvoidance = true,
Year = ,
Dealer = d3
};
var c3 = new Toyota
{
Model = "Tundra",
Color = "Blue",
Year = ,
Dealer = d2
};
context.Dealers.Add(d1);
context.Dealers.Add(d2);
context.Dealers.Add(d3);
context.SaveChanges();
} using (var context = new Recipe12Context())
{
Console.WriteLine("Dealers and Their Cars");
Console.WriteLine("======================");
foreach (var dealer in context.Dealers)
{
Console.WriteLine("\nDealer: {0}", dealer.Name);
foreach (var car in dealer.Cars)
{
string make = string.Empty;
if (car is Toyota)
make = "Toyota";
else if (car is BMW)
make = "BMW";
Console.WriteLine("\t{0} {1} {2} {3}", car.Year,
car.Color, make, car.Model);
}
}
}

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

Dealer: Luxury Auto World
Blue BMW 310i
Dealer: Southtown Toyota
Blue Toyota Tundra
Dealer: All Cities Toyota
Green Toyota Camry

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

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

《Entity Framework 6 Recipes》中文翻译系列 (36) ------ 第六章 继承与建模高级应用之TPC继承映射的更多相关文章

  1. 《Entity Framework 6 Recipes》中文翻译系列 (30) ------ 第六章 继承与建模高级应用之多对多关联

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第六章  继承与建模高级应用 现在,你应该对实体框架中基本的建模有了一定的了解,本章 ...

  2. 《Entity Framework 6 Recipes》中文翻译系列 (31) ------ 第六章 继承与建模高级应用之自引用关联

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-4  使用TPH建模自引用关系 问题 你有一张自引用的表,它代表数据库上不同类型 ...

  3. 《Entity Framework 6 Recipes》中文翻译系列 (32) ------ 第六章 继承与建模高级应用之TPH与TPT (1)

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-6  映射派生类中的NULL条件 问题 你的表中,有一列允许为null.你想使用 ...

  4. 《Entity Framework 6 Recipes》中文翻译系列 (33) ------ 第六章 继承与建模高级应用之TPH与TPT (2)

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-8  嵌套的TPH建模 问题 你想使用超过一层的TPH继承映射为一张表建模. 解 ...

  5. 《Entity Framework 6 Recipes》中文翻译系列 (34) ------ 第六章 继承与建模高级应用之多条件与QueryView

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-10  创建一个多条件过滤 问题 你想使用多个条件为实体过滤表中的行. 解决方案 ...

  6. 《Entity Framework 6 Recipes》中文翻译系列 (35) ------ 第六章 继承与建模高级应用之TPH继承映射中使用复合条件

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-11  TPH继承映射中使用复合条件 问题 你想使用TPH为一张表建模,建模中使 ...

  7. 《Entity Framework 6 Recipes》中文翻译系列 (37) ------ 第六章 继承与建模高级应用之独立关联与外键关联

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-13  在基类中应用条件 问题 你想从一个已存在的模型中的实体派生一个新的实体, ...

  8. 《Entity Framework 6 Recipes》翻译系列 (1) -----第一章 开始使用实体框架之历史和框架简述

    微软的Entity Framework 受到越来越多人的关注和使用,Entity Framework7.0版本也即将发行.虽然已经开源,可遗憾的是,国内没有关于它的书籍,更不用说好书了,可能是因为EF ...

  9. 《Entity Framework 6 Recipes》翻译系列 (4) -----第二章 实体数据建模基础之从已存在的数据库创建模型

    不知道对EF感兴趣的并不多,还是我翻译有问题(如果是,恳请你指正),通过前几篇的反馈,阅读这个系列的人不多.不要这事到最后成了吃不讨好的事就麻烦了,废话就到这里,直奔主题. 2-2 从已存在的数据库创 ...

随机推荐

  1. 基于.NET平台常用的框架整理

    自从学习.NET以来,优雅的编程风格,极度简单的可扩展性,足够强大开发工具,极小的学习曲线,让我对这个平台产生了浓厚的兴趣,在工作和学习中也积累了一些开源的组件,就目前想到的先整理于此,如果再想到,就 ...

  2. RadioButton(单选按钮)文字在按钮的左边

    <RadioButton style="@style/CustomCheckboxTheme" android:layout_width="fill_parent& ...

  3. 支付宝支付-APP支付服务端详解

    支付宝APP支付服务端详解 前面接了微信支付,相比微信支付,支付宝APP支付提供了支付分装类,下面将实现支付宝APP支付.订单查询.支付结果异步通知.APP支付申请参数说明,以及服务端返回APP端发起 ...

  4. 手持移动扫描终端 PDA移动开单系统-批发零售管理

    条码数据采集器通过扫描商品条码移动开单,实现便携式办公,伴随式销售,是我公司的一款最新便携式开单配套产品,采集器能通过WIFI无线局域网.GPRS互联网直接与主机连接,让公司业务人员能随时随地了解公司 ...

  5. 同一台电脑上多个myeclipse破解的问题

    因为项目版本的问题,电脑上不得装了个myeclipe10版本的,但是破解之后,原来电脑上的myeclipse2014却显 示没有激活,好吧,我又去把myeclipse2014重新激活了一遍,但是到了m ...

  6. xsl: normalize-space(string str) 函数

    本文出自http://technet.microsoft.com/zh-cn/magazine/ms256063%28VS.90%29.aspx 通过去掉前导和尾随空白并使用单个空格替换一系列空白字符 ...

  7. 【统计学习】主成分分析PCA(Princple Component Analysis)从原理到实现

    [引言]--PCA降维的作用 面对海量的.多维(可能有成百上千维)的数据,我们应该如何高效去除某些维度间相关的信息,保留对我们"有用"的信息,这是个问题. PCA给出了我们一种解决 ...

  8. 基于redis的点赞功能设计

    前言 点赞其实是一个很有意思的功能.基本的设计思路有大致两种, 一种自然是用mysql等 数据库直接落地存储, 另外一种就是利用点赞的业务特征来扔到redis(或memcache)中, 然后离线刷回m ...

  9. DateTable利用NPOI导出Excel 公共方法

    protected void Export_Excel(DataTable dt) { string filename = "学生基本信息.xls"; ) { filename = ...

  10. redhat6 yum源配置

    第一次接触redhat系统,安装软件时,发现没有ubuntu的apt-get包管理器,自带的yum包管理器又什么都找不到,网上搜了好久,终于把yum配置好了,感谢博主们- 使用redhat系统自带的y ...