翻译的初衷以及为什么选择《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 &lt;
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的更多相关文章

  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》中文翻译系列 (35) ------ 第六章 继承与建模高级应用之TPH继承映射中使用复合条件

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-11  TPH继承映射中使用复合条件 问题 你想使用TPH为一张表建模,建模中使 ...

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

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

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

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-13  在基类中应用条件 问题 你想从一个已存在的模型中的实体派生一个新的实体, ...

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

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

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

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

随机推荐

  1. [算法总结]partition (quicksort)

    private int partition(int[] nums, int lo, int hi) { if (lo >= hi) { return lo; } int i = lo; int ...

  2. C#启用管理员权限运行程序

    方法一:关闭程序重新请求打开 static class Program { [STAThread] static void Main() { Application.EnableVisualStyle ...

  3. RStudio技巧02_Extract Function

    RStudio 可以在 source 编辑器中分析一组选择的代码,并自动将其转化成再次使用的函数.任何选择中的"free"变量( 选择引用对象但不创建)将转化为函数参数. (也可使 ...

  4. 关于jquery简单操作简单表格

    最近在摸索jquery中,想着学习过程中还是记下点自己的东西比较好,不管是日后自己查阅,亦或是对于他人有些许帮助. 也是一件两全其美的事情了. 下面我就简单 贴上自己的html中重要部分了. 具体实现 ...

  5. bfrd collector性能排查

     1.2.09上昨天timeout在18点23分-22点10分 2.检测2.17网卡流量,sar -f /var/log/sa/sa06 -n DEV,发现这段时间刚好是rxpck/s超过6400. ...

  6. js中substr,substring,indexOf,lastIndexOf的用法小结

    第一组:str.substr(start,length) 和 str.substring(start,end) 定义: str.substr(start,length) substr(start,le ...

  7. tomcat在linux下自启动

    Linux下设置tomcat开机自启动  一.以root用户登录系统: 二.进入init.d文件夹 cd /etc/init.d/ 三.创建并打开tomcat文件 vi tomcat 四.tomcat ...

  8. MySQL表名和数据库关键字相同解决办法

    今天改他们的代码的时候,遇到了MySQL表名和数据库关键字的问题. 由于表名是关键字,导致增删改查都报错. Hibernate: select leave0_.id as id22_, leave0_ ...

  9. iphone中input标签会多出一块的解决办法

    -webkit-appearance: none;

  10. 【luogu】 P1880 石子合并

    原题原题原题原题原题 先贴上错误代码... ↓错误代码↓ #include <iostream> #include <cstdio> #include <cstring& ...