翻译的初衷以及为什么选择《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. SpringMVC(六) RequestMapping 路径中ant风格的通配符

    SpringMVC支持路径中包含ant风格的通配符,常用的几种通配符及意义如下: ? 任意一个字符 * 任意多个字符 ** 匹配多层路径 测试控制器代码: package com.tiekui.spr ...

  2. WebGL入门教程(三)-webgl动画

    前面文章: WebGL入门教程(一)-初识webgl WebGL入门教程(二)-webgl绘制三角形 WebGL动画有移动.旋转和缩放,我们将移动.旋转和缩放图形,然后将其绘制到屏幕上,称为变换(tr ...

  3. 第四章 springboot + swagger

    http://www.cnblogs.com/java-zhao/p/5348113.html

  4. 原生js实现查询天气的小应用

    demo:https://zsqosos.github.io/weather/ 截图: 实现功能:打开网页时显示用户所在城市的天气状况,在输入框输入城市可查询其它城市. 实现过程:先调用百度地图的AP ...

  5. bzoj3110树套树

    wa一片,最后一个T,终于心碎了... 为什么没人告诉我要开longlong 为什么所有人都说没有负数 #include<cstdio> #include<algorithm> ...

  6. Asp.net 配置web.Config 在出错时跳转到相应页面

    <!--<customErrors mode="On" defaultRedirect="error.aspx">      <erro ...

  7. grep 信息提取

    1.提取svn版本库的版本号 svn info |grep -Po '(?<=Revision: )[0-9]*'

  8. c#文本转语音以及语音阅读小实例

    c#实现语音阅读以及文本转语音文件是基于c#的一个类库(SpeechSynthesizer )实现的,使用该类必须要添加引用using System.Speech.Synthesis;直接是无法添加引 ...

  9. VMware创建Linux虚拟机并安装CentOS(三)

    选择“创建自定义布局”手动给Linux指定系统分区.交换分区,鼠标单击“下一步”按钮继续. 首先创建交Swap分区,鼠标单击“创建”按钮,在弹出的“生成存储”对话框中,生成分区选择“标准分区”:鼠标单 ...

  10. json相关的一些用法

    一. json可以表示3种类型的值:   简单值 . 对象. 数组    表示对象时:>1. 没有变量的概念 ,所以不用申明变量                    >2. 没有末尾结束 ...