《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类型
using (var context = new Recipe13Context())
{
context.Invoices.Add(new Invoice
{
Amount = 19.95M,
Description = "Oil Change",
Date = DateTime.Parse("4/11/13")
});
context.Invoices.Add(new Invoice
{
Amount = 129.95M,
Description = "Wheel Alignment",
Date = DateTime.Parse("4/01/13")
});
context.Invoices.Add(new DeletedInvoice
{
Amount = 39.95M,
Description = "Engine Diagnosis",
Date = DateTime.Parse("4/01/13")
});
context.SaveChanges();
} using (var context = new Recipe13Context())
{
foreach (var invoice in context.Invoices)
{
var isDeleted = invoice as DeletedInvoice;
Console.WriteLine("{0} Invoice",
isDeleted == null ? "Active" : "Deleted");
Console.WriteLine("Description: {0}", invoice.Description);
Console.WriteLine("Amount: {0:C}", invoice.Amount);
Console.WriteLine("Date: {0}", invoice.Date.ToShortDateString());
Console.WriteLine();
}
}
代码清单6-37的输出如下:
Active Invoice
Description: Oil Change
Amount: $19.95
Date: //
Active Invoice
Description: Wheel Alignment
Amount: $129.95
Date: //
Deleted Invoice
Description: Engine Diagnosis
Amount: $39.95
Date: //
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/
《Entity Framework 6 Recipes》中文翻译系列 (37) ------ 第六章 继承与建模高级应用之独立关联与外键关联的更多相关文章
- 《Entity Framework 6 Recipes》中文翻译系列 (30) ------ 第六章 继承与建模高级应用之多对多关联
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第六章 继承与建模高级应用 现在,你应该对实体框架中基本的建模有了一定的了解,本章 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (31) ------ 第六章 继承与建模高级应用之自引用关联
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-4 使用TPH建模自引用关系 问题 你有一张自引用的表,它代表数据库上不同类型 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (32) ------ 第六章 继承与建模高级应用之TPH与TPT (1)
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-6 映射派生类中的NULL条件 问题 你的表中,有一列允许为null.你想使用 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (33) ------ 第六章 继承与建模高级应用之TPH与TPT (2)
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-8 嵌套的TPH建模 问题 你想使用超过一层的TPH继承映射为一张表建模. 解 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (34) ------ 第六章 继承与建模高级应用之多条件与QueryView
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-10 创建一个多条件过滤 问题 你想使用多个条件为实体过滤表中的行. 解决方案 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (35) ------ 第六章 继承与建模高级应用之TPH继承映射中使用复合条件
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-11 TPH继承映射中使用复合条件 问题 你想使用TPH为一张表建模,建模中使 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (36) ------ 第六章 继承与建模高级应用之TPC继承映射
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-12 TPC继承映射建模 问题 你有两张或多张架构和数据类似的表,你想使用TP ...
- 《Entity Framework 6 Recipes》翻译系列 (1) -----第一章 开始使用实体框架之历史和框架简述
微软的Entity Framework 受到越来越多人的关注和使用,Entity Framework7.0版本也即将发行.虽然已经开源,可遗憾的是,国内没有关于它的书籍,更不用说好书了,可能是因为EF ...
- 《Entity Framework 6 Recipes》翻译系列 (4) -----第二章 实体数据建模基础之从已存在的数据库创建模型
不知道对EF感兴趣的并不多,还是我翻译有问题(如果是,恳请你指正),通过前几篇的反馈,阅读这个系列的人不多.不要这事到最后成了吃不讨好的事就麻烦了,废话就到这里,直奔主题. 2-2 从已存在的数据库创 ...
随机推荐
- 【Hibernate框架】flush机制
背景: 一个偶然的机会,我做了一个例子,中间我遇到了一个有意思的问题,就是在执行commit方法之前,做了两次save操作,如下: SessionFactory sf = new Configurat ...
- Go语言 模板的使用(一)
使用Parse package main import ( "html/template" "net/http" ) func SayHello(w http. ...
- 字典树+博弈 CF 455B A Lot of Games(接龙游戏)
题目链接 题意: A和B轮流在建造一个字,每次添加一个字符,要求是给定的n个串的某一个的前缀,不能添加字符的人输掉游戏,输掉的人先手下一轮的游戏.问A先手,经过k轮游戏,最后胜利的人是谁. 思路: 很 ...
- org.openqa.selenium.remote.SessionNotFoundException: Unexpected error launch IE
1.在启动ie浏览器前先加入属性设置一项: DesiredCapabilities ie = DesiredCapabilities.internetExplorer(); ie.setCapabil ...
- C#开发笔记
Dictionary 检查后获取值:Dictionary.TryGetValue() KeyValuePair<T, K> 的非泛型形式:DictionaryEntry List 由ILi ...
- CSharp数据库代码生成工具
项目中遇到很多数据库表字段特别多的项目,手动一个一个去敲也不知道敲到什么时候,突发奇想做一个工具一劳永逸.花了一晚上做了这个东西,代码写的比较乱,用这个工具后减少了很多时间. Git地址:https: ...
- js 判断浏览器和ie版本号 收集
function testB () { // body... var isOpera = !!window.opera ||!!window.opr|| navigator.userAgent.ind ...
- tornado 学习笔记17 HTTPServerRequest分析
代表Http请求. 所有的属性都是字符串型. 17.1 属性 (1) method:请求方法类型,比如"GET"."POST" (2) ur ...
- *HDU2254 矩阵乘法
奥运 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submissi ...
- 在SQLSERVER里,怎么让别人只能输入一个字母的约束该怎么写?就是26个字母中的任意一个?
alter table 表名 add constraint ck_char check(自段名 like '[a-z]' or 自段名 like '[A-Z]')