《Entity Framework 6 Recipes》中文翻译系列 (34) ------ 第六章 继承与建模高级应用之多条件与QueryView
翻译的初衷以及为什么选择《Entity Framework 6 Recipes》来学习,请看本系列开篇
6-10 创建一个多条件过滤
问题
你想使用多个条件为实体过滤表中的行。
解决方案
假设你有一张处理网站订单的表,如图6-13所示。

图6-13 表WebOrder包含网站订单的信息
假设我们有这样一个业务需求,WebOrder中的实例为,2012年以后的,2010年到2012年之间未删除的,2010年以前的订单金额大于200美元的。这样的复杂过滤条件不能使用映射详细信息窗口中有限制的条件来创建了。 有一种实现方法是使用QueryView。按下面的步骤,使用QueryView来为这个实体和满足业务需要的条件建模:
1、在你的项目中添加一个ADO.NET Entity Data Model(ADO.NET实体数据模型),并导入表WebOrder。使用代码清单6-27中的代码创建存储过程。接下来的两步,我们将为WebOrder实体映射insert,update和delete动作。
代码清单6-27. 在数据库中为WebOrder实体定义的Insert,Update和Delete动作
create procedure [Chapter6].[InsertOrder]
(@CustomerName varchar(50),@OrderDate date,@IsDeleted bit,@Amount decimal)
as
begin
insert into chapter6.WebOrder (CustomerName, OrderDate, IsDeleted, Amount)
values (@CustomerName, @OrderDate, @IsDeleted, @Amount)
select SCOPE_IDENTITY() as OrderId
end
go
create procedure [Chapter6].[UpdateOrder]
(@CustomerName varchar(50),@OrderDate date,@IsDeleted bit,
@Amount decimal, @OrderId int)
as
begin
update chapter6.WebOrder set CustomerName = @CustomerName,
OrderDate = @OrderDate,IsDeleted = @IsDeleted,Amount = @Amount
where OrderId = @OrderId
end
go
create procedure [Chapter6].[DeleteOrder]
(@OrderId int)
as
begin
delete from Chapter6.WebOrder where OrderId = @OrderId
end
2、右键设计器,并选择Update Model from Database(从数据库更新模型)。在更新向导中,选择存储过程InsertOrder,UpdateOrder和DeleteOrder。
3、选择WebOrder实体,并查看Mapping Details window(映射详细信息窗口)。单击Map Entity to Function(映射实体到函数)按钮。这个按钮是在映射详细信息窗口左边最下边的一个按钮。映射Insert、Update和Delete动作到存储过程。prperty/parameter(属性/参数)映射会自动填入。然而,存储过程InsertOrder的返回值必须映射到OrderId属性。这是实体框架用于在插入操作后获取标识列OrderId值的途径。正确映射如图6-14所示。

图6-14 存储过程/动作映射详细信息
4、在映射详细信息窗口中选择映射表(最上边的按钮)。删除WebOrder表的映射。我们将在后面使用QueryView来映射;
在解决方案浏览器中右键.edmx文件,选择Open With(打开方式) ➤XML Editor(XML文本编辑器)。在C-S映射层,将代码清单6-28中的查询视图(QueryView)插入到标签<EntitySetMapping>中,QueryView将映射实体WebOrder。
小心!C-S映射层的修改会在下一次从数据库更新模型时丢失。
代码清单6-28. 使用QueryView为WebOrder表映射实体集
<EntitySetMapping Name="WebOrders">
<QueryView>
select value
Apress.EF6Recipes.BeyondModelingBasics.Recipe10.WebOrder(o.OrderId,
o.CustomerName,o.OrderDate,o.IsDeleted,o.Amount)
from ApressEF6RecipesBeyondModelingBasicsRecipe10StoreContainer.WebOrder as o
where (o.OrderDate > datetime'2012-01-01 00:00') ||
(o.OrderDate between cast('2010-01-01' as Edm.DateTime) and
cast('2012-01-01' as Edm.DateTime) and !o.IsDeleted) ||
(o.Amount > 200 and o.OrderDate <
cast('2010-01-01' as Edm.DateTime))
</QueryView>
</EntitySetMapping>
原理
QueryView是一种只读映射,它可以用来代替实体框架为我们提供的默认映射。当QueryView在映射层标签<EntitySetMapping>中时,它将映射存储层定义的表和在概念模型层中定义的实体。当它在标签<AssociationSetMapping>中时,它将映射存储层中的关系和概念模型中的关联。QueryView的通常用法是,用在标签<AssociationSetMapping>中,用它来实现基于条件的,且不能通过默认的条件映射来实现的继承映射。
QueryView使用Entity SQL来表示,QueryView只能查询在概念模型定义的实体。另外,QueryView中的eSQL不支持gourp by和group聚合。
当实体使用QueryView来映射时,实体框架对这精确的映射实现浑然不知。这是因为实体框架不知道底层的表和列用来创建实体的实例,它不能产生适当的存储层动作来插入、更新或者删除实体。实体被实例化后,实体框架也不会进行跟踪。它不知道底层如何修改实体。
实现插入、更新和删除动作的责任落到了开发员人的头上,这些动作可以直接在.edmx文件中实现,也可以在数据库使用存储过程来实现。为了管理这些动作的存储过程,你需要创建<ModificationFunctionMapping>节。我们在第四步使用设计器而不是直接修改.edmx文件的方式来实现的。
如果使用QueryView映射的实体与别的实体之间有关联,这些关联及其关联的实体都需要使用QueryView来映射。当然,这会变得相当麻烦。QueryView是一个强有力的工具,但当很快就会成为我们的负担。
下面是QueryView的常见使用场景:
1、定义一个不被支持的过滤条件,比如:大于,小于等等;
2、映射基于除了is null,not null或者equal to条件的继承;
3、映射一列计算后的列,或是从表中返加列的子集,或是为了改变限制或类型为Data的列,例如,让它为可空类型,将一字符串列显现为整型;
4、映射基于不同主键和外键的TPT继承映射;
5、映射存储层相同的列到概念模型中不同的类型;
6、映射多个类型到同一张表;
代码清单6-28中,QueryView里包含一个Entity SQL语句,它包含三个部分。第一个部分是select从句,使用构造函数实例化一个WebOrder实例。构造函数获取属性值的顺序跟我们在概念模型中定义的顺序一至,如代码清单6-29所示。
代码清单6-29.概念模型中WebOrder实体的定义
<EntityType Name="WebOrder">
<Key>
<PropertyRef Name="OrderId" />
</Key>
<Property Name="OrderId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="CustomerName" Type="varchar" Nullable="false" MaxLength="255" />
<Property Name="OrderDate" Type="datetime" Nullable="false" />
<Property Name="IsDeleted" Type="bit" Nullable="false" />
<Property Name="Amount" Type="money" />
</EntityType>
注意,在代码清单6-28中的Entity SQL中,在创建WebOrder实体的实例时,我们完全限定命名空间EFRecipesModel。我们在from从句中同样限定了存储容器EFRecipesModelStoreContainer。
在Entity SQL表达式中的最后一节,包含了where从句,它是我们这个示例使用QueryView的原因。虽然where从句可以任意的复杂,但它受上面看到的QueryView中的Entity SQL限制。
代码清单6-30演示了,在模型中插入和获取WebOrders。
代码清单6-30.插入和获取WebOrder实体
using (var context = new Recipe10Context())
{
var order = new WebOrder
{
CustomerName = "Jim Allen",
OrderDate = DateTime.Parse("5/3/2012"),
IsDeleted = false,
Amount =
};
context.WebOrders.Add(order);
order = new WebOrder
{
CustomerName = "John Stevens",
OrderDate = DateTime.Parse("1/1/2011"),
IsDeleted = false,
Amount =
};
context.WebOrders.Add(order);
order = new WebOrder
{
CustomerName = "Russel Smith",
OrderDate = DateTime.Parse("1/3/2011"),
IsDeleted = true,
Amount =
};
context.WebOrders.Add(order);
order = new WebOrder
{
CustomerName = "Mike Hammer",
OrderDate = DateTime.Parse("6/3/2013"),
IsDeleted = true,
Amount =
};
context.WebOrders.Add(order);
order = new WebOrder
{
CustomerName = "Steve Jones",
OrderDate = DateTime.Parse("1/1/2008"),
IsDeleted = true,
Amount =
};
context.WebOrders.Add(order);
context.SaveChanges();
} using (var context = new Recipe10Context())
{
Console.WriteLine("Orders");
Console.WriteLine("======");
foreach (var order in context.WebOrders)
{
Console.WriteLine("\nCustomer: {0}", order.CustomerName);
Console.WriteLine("OrderDate: {0}", order.OrderDate.ToShortDateString());
Console.WriteLine("Is Deleted: {0}", order.IsDeleted.ToString());
Console.WriteLine("Amount: {0:C}", order.Amount);
}
}
代码清单6-30的输出如下。注意,只有满足我们在QueryView中,使用Entity SQL表达式定义的条件的customers才被显示。
Orders...
Customer: John Stevens
Order Date: //
Is Deleted: False
Amount: $400.00
Customer: Jim Allen
Order Date: //
Is Deleted: False
Amount: $200.00
Customer: Mike Hammer
Order Date: //
Is Deleted: True
Amount: $,800.00
实体框架交流QQ群: 458326058,欢迎有兴趣的朋友加入一起交流
谢谢大家的持续关注,我的博客地址:http://www.cnblogs.com/VolcanoCloud/
《Entity Framework 6 Recipes》中文翻译系列 (34) ------ 第六章 继承与建模高级应用之多条件与QueryView的更多相关文章
- 《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》中文翻译系列 (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》中文翻译系列 (37) ------ 第六章 继承与建模高级应用之独立关联与外键关联
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-13 在基类中应用条件 问题 你想从一个已存在的模型中的实体派生一个新的实体, ...
- 《Entity Framework 6 Recipes》翻译系列 (1) -----第一章 开始使用实体框架之历史和框架简述
微软的Entity Framework 受到越来越多人的关注和使用,Entity Framework7.0版本也即将发行.虽然已经开源,可遗憾的是,国内没有关于它的书籍,更不用说好书了,可能是因为EF ...
- 《Entity Framework 6 Recipes》翻译系列 (4) -----第二章 实体数据建模基础之从已存在的数据库创建模型
不知道对EF感兴趣的并不多,还是我翻译有问题(如果是,恳请你指正),通过前几篇的反馈,阅读这个系列的人不多.不要这事到最后成了吃不讨好的事就麻烦了,废话就到这里,直奔主题. 2-2 从已存在的数据库创 ...
随机推荐
- .NET 项目代码风格要求
原文:http://kb.cnblogs.com/page/179593/ 项目代码风格要求 PDF版下载:项目代码风格要求V1.0.pdf 代码风格没有正确与否,重要的是整齐划一,这是我拟的一份&l ...
- Good Bye 2016 - C
题目链接:http://codeforces.com/contest/750/problem/C 题意:在CF中,每个人都有个Rank值. 当Rank>=1900时,为DIV1.Rank< ...
- centos 研究
默认工具: yum , (Ubuntu: apt-get)
- UGUI全面实践教程
UGUI全面实践教程 试读文档下载地址:http://pan.baidu.com/s/1hq3UYGk 介绍:UGUI是Unity官方推出的最新UI系统.本教程为国内唯一的UGUI专向资料.本教程 ...
- 指定eclipse启动使用的JVM
不同eclispe对运行时要求不一样,而一台电脑只能同时使用一个运行时,当多个要求不同版本jvm的eclipse需要在一台电脑工作时,需要手动指定eclipse启动使用的jvm. [eclipse-j ...
- iOS10以上关于访问权限设置
记录一下: iOS对用户的安全和隐私的增强,在申请很多私有权限的时候都需要添加描述,但是,在使用Xcode 8之前的Xcode还是使用系统的权限通知框.要想解决这个问题,只需要在info.plist添 ...
- github push时,要求密码的问题
整几次才搞的有点明白: 1 clone 项目 用 SSH: 在github 上如下图 2 C:\Users\<用户名> 下如果有 "_netrc" 文件: 如果含有 如 ...
- 矩阵快速幂 HDU 4565 So Easy!(简单?才怪!)
题目链接 题意: 思路: 直接拿别人的图,自己写太麻烦了~ 然后就可以用矩阵快速幂套模板求递推式啦~ 另外: 这题想不到或者不会矩阵快速幂,根本没法做,还是2013年长沙邀请赛水题,也是2008年Go ...
- 记录同事的一个bug-ajax-413错误-fullhead
症状表现为在form下面的textarea里的字符数只有几十个的时候,请求可以成功,但是如果有几百字,则会出现413错误,提示fullhead,我第一反应是cookie体积太小,但是清了缓存还是一样的 ...
- 将excel数据读入matlab
1.[NUM,TXT,RAW]=xlsread('example'),其中example是你的excel名,假设所有的数据都在example.xls中. 2.NUM返回的是excel中的数据,TXT输 ...