翻译的初衷以及为什么选择《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) ------ 第六章 继承与建模高级应用之独立关联与外键关联的更多相关文章

  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》中文翻译系列 (36) ------ 第六章 继承与建模高级应用之TPC继承映射

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-12  TPC继承映射建模 问题 你有两张或多张架构和数据类似的表,你想使用TP ...

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

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

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

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

随机推荐

  1. WooCommerce

    http://devework.com/woocommerce.html https://woocommerce.com/ https://woocommerce.com/product-catego ...

  2. 学习微信小程序之css4设置颜色,单位表示,字体样式

    颜色的设置可以通过RGB设置 可以直接通过英文单词设置 可以通过16进制来设置 长度单位: 字体样式: 设置字体样式 字体粗细 设置字体风格 设置字间距

  3. Qt中暂停线程的执行

    在线程中定义一个信号量 QMutex pause; 把run()函数中循环执行的部分用信号量pause锁住: void run() { while(1) { pause.lock(); //循环执行的 ...

  4. unity3d关于碰撞问题

    这个是我做忍者游戏出现的问题,做个记录也为以后有人遇到也可以借鉴.因为刚接触unity,所以对其所知甚少,说错的地方请指教. 问题:角色碰撞墙为什么会先触发碰撞地面,然后再触发碰撞墙 想要的效果:是角 ...

  5. JS代码判断IE6,IE7,IE8,IE9!

    JS代码判断IE6,IE7,IE8,IE9!2011年12月15日 星期四 14:01做网页有时候会用到JS检测IE的版本,下面是检测Microsoft Internet Explorer版本的三种代 ...

  6. some useful linux commands

    # best way to see log file less +F /var/log/syslog (equals: less /var/log/syslog, then shift+f) # se ...

  7. View 与 Controller 之间的delegate(代理)传值

    这个代理传值是经常使用的一种传值方式,下面介绍一种View 和 Controller 之间的代理传值方法. 先建立一个View视图 如 LoginView 是继承于一个UIView 在LoginVie ...

  8. tungsten抽取和应用mysql binlog

    首先举例说明 api的基本使用方式 首先进行配置 , 可以看到源数据库和目的数据库 TungstenProperties tp=new TungstenProperties(); tp.setStri ...

  9. DIV+CSS自适应布局

    自适应布局分两类:高度和宽度,方法有很多,我用三列布局举例,我就列几个通俗易懂的例子呗,懂了三列的,两列的原理一样,呵呵哒. 效果图如下:高度自适应——宽度自适应            1,高度自适应 ...

  10. ajax+div 代替iframe 学习尝试

    工作的时候遇到了所谓html内多tab展示的情况,主要是通过iframe来关联子页面: 不过也不知道从何时开始记得是说iframe不建议多用,所以想想,还是找找有没有其他方法(不应用于工作): 先说下 ...