翻译的初衷以及为什么选择《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. Redis 数据库入门指南

    Redis 是一个开源数据库,它使用内存数据结构存储,可作为数据库.缓存和消息代理使用.Redis 支持丰富的数据结构,有:字符串(Strings).哈希(Hashs).列表(Lists).集合(Se ...

  2. 安装hadoop+zookeeper ha

    安装hadoop+zookeeper ha 前期工作配置好网络和主机名和关闭防火墙 chkconfig iptables off //关闭防火墙 1.安装好java并配置好相关变量 (/etc/pro ...

  3. APPCAN开发笔记:html页面之间的参数传递:使用js获取url中的参数,以及在APPCAN中不能使用的解决方法

    用PHP的GET/POST方式来传递方式已经是司空见惯了,但是如果我的页面是一个静态的html的页面,想传递参数的时候要怎么办呢?在APPCAN的开发中我们会经常遇到这样的问题,因为所有的页面都是静态 ...

  4. 毕业论文中使用的技术—FileReader接口

    用来把文件读入内存,并且读取文件中的数据. FileReader接口提供了一个异步API,使用该API可以在浏览器主线程中异步访问文件系统,读取文件中的数据 FileReader接口的方法 方法名 参 ...

  5. Mybatis拦截器

    Mybatis拦截器

  6. 主机信息收集工具DMitry

    主机信息收集工具DMitry   DMitry是Kali Linux内置的一款信息收集工具.它的目标主要是Web类主机.它不仅通过主动查询.端口扫描方式,还借助第三方网站和搜索引擎获取信息. 它搜集的 ...

  7. SQL Server 2012 数据库数据导出为脚本

    转自:http://blog.csdn.net/ituff/article/details/8265822 将高版本的的SQL Server数据库移到低版本的SQL Server是一件十分蛋疼的事,最 ...

  8. 获取终端ip地址

    网上找的,记录下 import java.io.*; import java.net.*; import java.util.*; //import org.apache.http.conn.util ...

  9. Linux mips64r2 PCI中断路由机制分析

    Linux mips64r2 PCI中断路由机制分析 本文主要分析mips64r2 PCI设备中断路由原理和irq号分配实现方法,并尝试回答如下问题: PCI设备驱动中断注册(request_irq) ...

  10. Access restriction: The type 'FileURLConnection' is not API

    遇到这种报错,解决方案如下: 报错原因是访问限制报错 工具栏中Project>preferences>java-Compiler>Errors/Warnings>把右侧的[De ...