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

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

6-13  在基类中应用条件

问题

  你想从一个已存在的模型中的实体派生一个新的实体,允许基类被实例化。

解决方案

  假设你有如图6-20所示的模型。

图6-20 包含Invoice实体的模型

  这个模型只包含一个单独的实体Invoice(发货单)。我们想从Invoice派生一个新的实体,它表示删除掉的发货单。这将允许我们以更清晰的业务逻辑来分别对有效的发货单和已删除掉的发货进行不同的操作。按下面的步骤,添加这个派生类型:

    1、在Mapping Details window(映射详细信息窗口)查看实体Invoice的信息,在IsDeleted列上添加一个条件,When IsDeleted =0(当IsDeleted列值为0),如图6-21所示。

图6-21 当IsDeleted列为0时映射Invoice实体

    2、现在IsDeleted列被用作条件,我们需要将其从实体的标量属性中移除。在实体Invoice的属性IsDeleted上右键,选择Delete(删除);

    3、右键设计器,并选择Add(新增)?Entity(实体)。命名新实体为DeletedInvoice,并选择Invoice作为基类;

    4、在Mapping Details window(映射详细信息窗口),查看实体DeletedInvoice的映射信息。将它映射到Invoice表,在IsDeleted列上添加一个条件,When IsDeleted =1(当IsDeleted列值为1),如图6-22所示。

图6-22 当IsDeleted列为1时映射DeletedInvoice实体

  包含Invoice实体和派生类型DeletedInvoice实体的最终模型,如图6-23所示。

图6-23 包含实体Invoice和DeletedInvoice的概念模型

 原理

  有两种不同的方式可以对我们的Invoice和DeletedInvoice建模。我们演示的这种方法,只是在如下情况下推荐使用,你有一个已经存在的模型和代码库,你想添加派生类型实体DeletedInvoice, 并对已有代码产生尽量少的影响。对于一个新模型,从基类Invoice派生一个ActiveInvoice类型和一个DeleteInvoice类型会更好。如果选择后面这种方法,你需要将基类标记为抽象类型。

  这里使用我们演示的这种方式,正如代码清单6-37所展示的那样,你可以决定,是选择casting还是OfType<>()方法来转换DeletedInvoice。但是,你不能单独select实体Invoice,这是这个方法最大的缺点。

代码清单6-37.使用as操作符来判断我们拥有的是一个Invoice类型还是DeletedInvoice类型

 1  using (var context = new Recipe13Context())
 2             {
 3                 context.Invoices.Add(new Invoice
 4                 {
 5                     Amount = 19.95M,
 6                     Description = "Oil Change",
 7                     Date = DateTime.Parse("4/11/13")
 8                 });
 9                 context.Invoices.Add(new Invoice
10                 {
11                     Amount = 129.95M,
12                     Description = "Wheel Alignment",
13                     Date = DateTime.Parse("4/01/13")
14                 });
15                 context.Invoices.Add(new DeletedInvoice
16                 {
17                     Amount = 39.95M,
18                     Description = "Engine Diagnosis",
19                     Date = DateTime.Parse("4/01/13")
20                 });
21                 context.SaveChanges();
22             }
23
24             using (var context = new Recipe13Context())
25             {
26                 foreach (var invoice in context.Invoices)
27                 {
28                     var isDeleted = invoice as DeletedInvoice;
29                     Console.WriteLine("{0} Invoice",
30                                       isDeleted == null ? "Active" : "Deleted");
31                     Console.WriteLine("Description: {0}", invoice.Description);
32                     Console.WriteLine("Amount: {0:C}", invoice.Amount);
33                     Console.WriteLine("Date: {0}", invoice.Date.ToShortDateString());
34                     Console.WriteLine();
35                 }
36             }

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

Active Invoice
Description: Oil Change
Amount: $19.95
Date: 4/11/2013
Active Invoice
Description: Wheel Alignment
Amount: $129.95
Date: 4/1/2013
Deleted Invoice
Description: Engine Diagnosis
Amount: $39.95
Date: 4/1/2013

6-14  创建独立关联和外键关联

问题

  你想使用Model First来创建独立关联和外键关联。

解决方案

  独立关联和外键关联帮助我们在数据库架构内维护引用完整性,并提供指向关联实体的导航路径。为了使用Model First创建外键和独立关联,请按下面的步骤操作:

    1、在你的项目中添加一新个ADO.NET Entity Data Model(ADO.NET实体数据模型),在提示选择模型内容时选择空模型,单击完成。这将创建一个空的计设界面;

    2、右键设计器,并选择Add(新增)?Entity(实体)。命名新实体为User,并单击OK(确定);

    3、右键新添加的实体,为其添加一个标量属性UserName;

    4、右键设计器,并选择Add(新增)?Entity(实体)。命名新实体为PassordHistory,并单击OK(确定);

    5、右键新添加的实体,为其添加一个标量属性LastLogin。右键LastLogin,改变其类型为DateTime;

    6、右键实体User,选择Add(增加) ?Association(关联)。创建外键关联,勾选Add froreign key properties to the PasswordHistory Entity(向“PassordHistory”实体中添加外键属性)复选框; 创建独立关联,就不要勾选。

    7、右键设计器,并选择Generate Model from Database(从数据库生成模型)。选择一个数据库连接,并完成接下来的向导。这将产生模型的存储层和映射层,并生成一个从模型生成 数据库的脚本。

  如果你选择创建一个外键关联,模型如图6-24所示。如果选择创建一个独立关联,模型如图6-25所示。

图6-24. User和PasswordHistory之间的外键关联

图6-25. User和PasswordHistory之间的独立关联

原理

  对于一个外键关联,外键被当作依赖实体的一个属性。暴露外键允许使用与管理别的属性值相同的代码,来管理关联的很多方面。最主要的帮助就是在离线场景,我们将会在第九章看到相关的内容。外键关联是实体模型的默认行为。

  对于独立关联,外键不会作为依赖实体的属性。这使得模型的概念层有几分清爽,因为这里没有引入关联的实现细节这种噪音。在早期的实体框架版本中只支持独立关联。

6-15  修改独立关联为外键关联

问题

  你一个使用独立关联的模型,你想把独立关联改变成一个外键关联。

解决方案

  假设你有如图6-26所示的模型。

图6-26. vehicles和tickets 间使用独立关联的模型

  按下面的步骤修改一个独立关联为外键关联:

    1、右键Ticket实体,选择Add(新增) ?Scalar Property(标量属性)。并重命名为LicenseNumber(牌照号码);

    2、在Mapping Details window(映射详细信息窗口)中查看关联的映射信息,从映射到Ticket控件中选择 <Delete>,移除Ticket表的映射;

    3、右键关联,查看properties(属性),单击引用约束控制按钮,在弹出的对话框中,在Principal(主体)下拉菜单中选择Vehicle。Principal Key(主体键)和Dependent Property(依赖属性)均设置为LicenseNumber,如图6-27所示。

图6-27. 为外键关联创建引用约束

    4、在Mapping Details window(映射详细信息窗口)中查看实体Ticket的映射信息,映射列LicenseNumber到属性LicenseNumber,如图6-28所示。

图6-28. 为实体ticket映射LicenseNumber属性到LicenseNumber列

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

图6-29. 独立关联修改为外键关联的模型

原理

  当你把独立关联修改成外键关联后,你已存在的绝大多数代码是可以正常运行的。你会发现,现在关联两个实体变得非常简单了,只需给外键属性设置合适的值 。在独立关联中改变一个关系,你需要为实体键创建一个新的实例,并设置实体的xxxReference.EntityKey为这个新的实例。在外键关联中,你只需要简单地设置外键属性的值为主键值。

  外键关联目前不支持多对多关联,因为这些关联必须被映射到底层的链接表。也许,在将来的实体框架的版本中,外键关联,通过附带载荷来支持多对多关联。

  至此,第六章结束,下篇我们将进入第七章,本篇有点长,感谢你的阅读!

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

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

时间: 2024-08-07 17:03:18

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

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

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第六章  继承与建模高级应用 现在,你应该对实体框架中基本的建模有了一定的了解,本章将帮助你解决许多常见的.复杂的建模问题,并解决你可能在现实中遇到的建模问题. 本章以多对多关系开始,这个类型的关系,无论是在现存系统还是新项目的建模中都非常普遍.接下来,我们会了解自引用关系,并探索获取嵌套对象图的各种策略.最后,本章以继承的高级建模和实体条件结束. 6-1  获取多对多关联中的链接表 问题

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

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-8  嵌套的TPH建模 问题 你想使用超过一层的TPH继承映射为一张表建模. 解决方案 假设你有一张员工(Employee)表,它包含各种类型的员工,比如,钟点工,雇员.如图6-10所示. 图6-10 包含各种类型的员工表 Employee表包含钟点工,雇员,提成员工,这是雇员下面的一个子类型.按下面的步骤,使用派生类型HourlyEmployee,SalariedEmployee和Sa

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

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-6  映射派生类中的NULL条件 问题 你的表中,有一列允许为null.你想使用TPH创建一个模型,列值为null时,表示一个派生类型,不为null时,表示另一个派生类型. 解决方案 假设你有一张表,描述医学实验药物.这张表包含一列指示该药是什么时候批准生产的.药在批准生产之前都被认为是实验性的.一但批准生产,它就被认为是药物了.我们就以图6-7中Drug表开始我们这一小节的学习. 图6

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

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-12  TPC继承映射建模 问题 你有两张或多张架构和数据类似的表,你想使用TPC继承映射为这些表建模. 解决方案 假设我们有如图6-18所示的表. 图6-18 表Toyota和BMW有相似的结构,它们可以成为派生至实体Car的派生类型 在图6-18中,表Toyota和BMW有相似的架构(Schema),并描述类似的数据.BMW表只多了额外的一列,它用一bit值来指示对应的实例是否具有避

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

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-10  创建一个多条件过滤 问题 你想使用多个条件为实体过滤表中的行. 解决方案 假设你有一张处理网站订单的表,如图6-13所示. 图6-13 表WebOrder包含网站订单的信息 假设我们有这样一个业务需求,WebOrder中的实例为,2012年以后的,2010年到2012年之间未删除的,2010年以前的订单金额大于200美元的.这样的复杂过滤条件不能使用映射详细信息窗口中有限制的条件

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

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-11  TPH继承映射中使用复合条件 问题 你想使用TPH为一张表建模,建模中使用的复杂条件超过了实框架能直接支持的能力. 解决方案 假设我们有一张Member表,如图6-15所示.Member表描述了我们俱乐部的会员信息.在我们的模型中,我们想使用TPH为派生类,AdultMember(成人会员).SeniorMember(老年人会员)和TeenMember(青少年会员)建模. 图6-

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

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-4  使用TPH建模自引用关系 问题 你有一张自引用的表,它代表数据库上不同类型但关联的对象.你想使用TPH为此表建模. 解决方案 假设你有一张如图6-5所示的表,它描述了关于人的事,人通常会有一个心中英雄,他最能激发自己.我们用一个指向Person表中的另一个行的引用来表示心中的英雄. 图6-5  包含不同角色的Person表 在现实中,每个人都会有一个角色,有的是消防员,有的是教师,

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

微软的Entity Framework 受到越来越多人的关注和使用,Entity Framework7.0版本也即将发行.虽然已经开源,可遗憾的是,国内没有关于它的书籍,更不用说好书了,可能是因为EF版本更新太快,没人愿意去花时间翻译国外关于EF的书籍.使用Entity Framework开发已经有3年多了,但用得很肤浅,最近想深入学习,只好找来英文书<Entity Framework 6 Recipes>第二版,慢慢啃.首先需要说明的是,我英文不好,只是为了学习EF.把学习的过程写成博客,一

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

不知道对EF感兴趣的并不多,还是我翻译有问题(如果是,恳请你指正),通过前几篇的反馈,阅读这个系列的人不多.不要这事到最后成了吃不讨好的事就麻烦了,废话就到这里,直奔主题. 2-2 从已存在的数据库创建模型 问题 有一个存在的数据库,它拥有表.也许还有视图.外键.你想通过它来创建一个模型. 解决方案 让我们设想,你拥有一个描述诗人(Poet)以及他们的诗(Poem),还有他们之间关系的数据库.如图2-7所示. 图2-7 一个关于诗人及他们的诗的简单数据库 从上图可以看出,一个诗人可能是一首或多首