Entity Framework 6 Recipes 2nd Edition(11-2)译 -> 用”模型定义”函数过滤实体集
11-2. 用”模型定义”函数过滤实体集
问题
想要创建一个”模型定义”函数来过滤一个实体集
解决方案
假设我们已有一个客户(Customer)和票据Invoice)模型,如Figure 11-2所示.

Figure 11-2. Customer and Invoice in a model
我们要想要创建一个”模型定义”函数获取invoice集并过滤出总数高于$300的invoice. 为了更有趣,让我们把一个"模型定义"函数用在一个查询中,这个查询进一步过滤出在5/1/2013之后创建的invoice. 当然,我们想要的是所有customer符合上述条件的invoice.
按下列步骤:
1.在解决方案中右击.edmx 文件,打开方式➤ XML编辑器.
2.在.edmx 文件中概念模型(conceptual models )小区里的<Schema> 标签下插入Listing 11-3所示的代码.
Listing 11-3. The GetInvoices() Model-Defined Function
<Function Name="GetInvoices" ReturnType="Collection(EFRecipesModel1102.Invoice)" >
<Parameter Name="invoices" Type="Collection(EFRecipesModel1102.Invoice)">
</Parameter>
<DefiningExpression>
Select VALUE i from invoices as i where i.Amount > 300M
</DefiningExpression>
</Function>
3.插入和查询模型的代码,如Listing 11-4所示的代码:
Listing 11-4.用eSQL 和LINQ两种方式用GetInvoices()方法(“模型定义”函数)来查询模型
class Program
{
static void Main(string[] args)
{
RunExample();
}
static void RunExample()
{
using (var context = new EFRecipesEntities1102())
{
DateTime d1 = DateTime.Parse("8/8/2013");
DateTime d2 = DateTime.Parse("8/12/2012");
var c1 = new Customer { Name = "Jill Robinson", City = "Dallas" };
var c2 = new Customer { Name = "Jerry Jones", City = "Denver" };
var c3 = new Customer { Name = "Janis Brady", City = "Dallas" };
var c4 = new Customer { Name = "Steve Foster", City = "Dallas" };
context.Invoices.Add(new Invoice
{
Amount = 302.99M,
Description = "New Tires",
Date = d1,
Customer = c1
});
context.Invoices.Add(new Invoice
{
Amount = 430.39M,
Description = "Brakes and Shocks",
Date = d1,
Customer = c2
});
context.Invoices.Add(new Invoice
{
Amount = 102.28M,
Description = "Wheel Alignment",
Date = d1,
Customer = c3
});
context.Invoices.Add(new Invoice
{
Amount = 629.82M,
Description = "A/C Repair",
Date = d2,
Customer = c4
});
context.SaveChanges();
}
using (var context = new EFRecipesEntities1102())
{
Console.WriteLine("Using eSQL query...");
string sql = @"Select value i from
EFRecipesModel1102.GetInvoices(EFRecipesEntities1102.Invoices) as i
where i.Date > DATETIME'2013-05-1 00:00'
and i.Customer.City = @City";
var objectContext = (context as IObjectContextAdapter).ObjectContext;
var invoices = objectContext.CreateQuery<Invoice>(sql,
new ObjectParameter("City", "Dallas")).Include("Customer");
foreach (var invoice in invoices)
{
Console.WriteLine("Customer: {0}\tInvoice for: {1}, Amount: {2}",
invoice.Customer.Name, invoice.Description, invoice.Amount);
}
}
using (var context = new EFRecipesEntities1102())
{
Console.WriteLine();
Console.WriteLine("Using LINQ query...");
DateTime date = DateTime.Parse("5/1/2013");
var invoices = from invoice in
MyFunctions.GetInvoices(context.Invoices)
where invoice.Date > date
where invoice.Customer.City == "Dallas"
select invoice;
foreach (var invoice in ((DbQuery<Invoice>)invoices)
.Include("Customer"))
{
Console.WriteLine("Customer: {0}, Invoice for: {1}, Amount: {2}",
invoice.Customer.Name, invoice.Description, invoice.Amount);
}
}
Console.WriteLine("\nPress any key to exit...");
Console.ReadKey();
}
}
public class MyFunctions
{
[EdmFunction("EFRecipesModel1102", "GetInvoices")]
public static IQueryable<Invoice> GetInvoices(IQueryable<Invoice> invoices)
{
return invoices.Provider.CreateQuery<Invoice>(
Expression.Call((MethodInfo)MethodInfo.GetCurrentMethod(),
Expression.Constant(invoices,typeof(IQueryable<Invoice>))));
}
}
代码Listing 11-4的输出结果如下:
Using eSQL for the query...
Customer: Jill Robinson Invoice for: New Tires, Amount: 302.99
Using LINQ for the query...
Customer: Jill Robinson, Invoice for: New Tires, Amount: 302.99
它是如何工作的?
从我们定义的Listing 11-3所示的GetInvoices()函数, 我们可以看到它接受一个Invoice集,并返回一个Invoice集.在运行时里,会解释为接受一个 IQueryable<Invoice> 并返回一个IQueryable<Invoice>.
在 eSQL表达式里, 我们把GetInvoices() 函数用在 from 子句里. 我们传递进去未过滤的Invoice集,然后我们的GetInvoices() 函数会返回一个过滤后的Invoice集. 我们进一步根据日期和Customer所有城市,用Where子句过滤这个集合. 接着我们用CreateQuery<Invoice>()来创建ObjectQuery<Invoice>类型. 在创建的查询里, 我们传递一个参数(客户所在的城市)来过滤并使用Include()方法来包含相关联的customer.一旦我们有了ObjectQuery<Invoice>, 我们遍历这个结果集并且过滤后符合条件的invoice打印出来.
用 LINQ 查询, 要有趣一些,我们把GetInvoices()方法放在了表达式的Form子句里,并把结果再根据日期和城市进行过滤(这点类似于eSQL表达式).然而,为了在LINQ查询中使用我们的函数,我们需要实现一个运行时方法,它接受一个IQueryable<Invoice> 并返回一个IQueryable<Invoice>.
与11-1小节里用”模型定义”函数返回一个标量值的方法存根不同,此处我们必须实现方法.创建该方法通常是参考引导程序
下面是引导程序的几个规则:
如果"模型定义"函数返回一个IQueryable<T>,必须使用引导程序
当一个函数返回一个IQueryable<T>,但不是接受一个IQueryable<T>, 引导方法必须实现为ObjectContext类的一部分
因为第二条规则,所以我们的ObjectContext在没有用一个IQueryable<T>开始的情况下,我们也不能返回一个IQueryable<T>.但我们可以传递进去一个IQueryable<T>, 接着在我们的引导方法里执行一些操作使它返回一个相关的IQueryable<T>. 尽管,我们不能在ObjectContext类以外手工创建一个IQueryable<T>,但像我们的例子里,我们接收一个IQueryable<T>作为参数后,可以为我们的ObjectContext在类外实现引导代码.
在我们实现的引导方法里,我们得到一个IQueryable<Invoice>.可以通过它的的Provider 属性得到一个IqueryProvider实例, IQueryProvider.CreateQuery<Invoice>()允许我们把IQueryable<T>加到表达树上
.当然此方法我们也使用了相关的”函数”特性来修饰,并传入一个invoice集.
Entity Framework 6 Recipes 2nd Edition(11-2)译 -> 用”模型定义”函数过滤实体集的更多相关文章
- Entity Framework 6 Recipes 2nd Edition 译 -> 目录 -持续更新
因为看了<Entity Framework 6 Recipes 2nd Edition>这本书前面8章的翻译,感谢china_fucan. 从第九章开始,我是边看边译的,没有通读,加之英语 ...
- Entity Framework 6 Recipes 2nd Edition(11-1)译 -> 从“模型定义”函数返回一个标量值
第11章函数 函数提供了一个有力代码复用机制, 并且让你的代码保持简洁和易懂. 它们同样也是EF运行时能利用的数据库层代码.函数有几类: Rowset Functions, 聚合函数, Ranking ...
- Entity Framework 6 Recipes 2nd Edition(11-2)译 -> 为一个”模型定义”函数返回一个计算列
11-3. 为一个”模型定义”函数返回一个计算列 问题 想从”模型定义”函数里返回一个计算列 解决方案 假设我们有一个员工(Employee)实体,属性有: FirstName, LastName,和 ...
- Entity Framework 6 Recipes 2nd Edition(9-3)译->找出Web API中发生了什么变化
9-3. 找出Web API中发生了什么变化 问题 想通过基于REST的Web API服务对数据库进行插入,删除和修改对象图,而不必为每个实体类编写单独的更新方法. 此外, 用EF6的Code Fri ...
- Entity Framework 6 Recipes 2nd Edition(9-4)译->Web API 的客户端实现修改跟踪
9-4. Web API 的客户端实现修改跟踪 问题 我们想通过客户端更新实体类,调用基于REST的Web API 服务实现把一个对象图的插入.删除和修改等数据库操作.此外, 我们想通过EF6的Cod ...
- Entity Framework 6 Recipes 2nd Edition(目录索引)
Chapter01. Getting Started with Entity Framework / 实体框架入门 1-1. A Brief Tour of the Entity Framework ...
- Entity Framework 6 Recipes 2nd Edition(9-1)译->用Web Api更新单独分离的实体
第九章 在N层结构的应用程序中使用EF 不是所有的应用都能完全地写入到一个单个的过程中(就是驻留在一个单一的物理层中),实际上,在当今不断发展的网络世界,大量的应用程序的结构包含经典的表现层,应用程, ...
- Entity Framework 6 Recipes 2nd Edition(13-2)译 -> 用实体键获取一个单独的实体
问题 不管你用DBFirst,ModelFirst或是CodeFirst的方式,你想用实体键获取一个单独的实体.在本例中,我们用CodeFirst的方式. 解决方案 假设你有一个模型表示一个Paint ...
- Entity Framework 6 Recipes 2nd Edition(13-3)译 -> 为一个只读的访问获取实体
问题 你想有效地获取只是用来显示不会更新的操作的实体.另外,你想用CodeFirst的方式来实现 解决方案 一个非常常见行为,尤其是网站,就是只是让用户浏览数据.大多数情况下,用户不会更新数据.在这种 ...
随机推荐
- mysql学习之 sql语句的技巧及优化
一.sql中使用正则表达式 select name,email from user where email Regexp "@163[.,]com$"; sql语句中使用Regex ...
- .NET平台开源项目速览(16)C#写PDF文件类库PDF File Writer介绍
1年前,我在文章:这些.NET开源项目你知道吗?.NET平台开源文档与报表处理组件集合(三)中(第9个项目),给大家推荐了一个开源免费的PDF读写组件 PDFSharp,PDFSharp我2年前就看过 ...
- shiro权限管理框架与springmvc整合
shiro是apache下的一个项目,和spring security类似,用于用户权限的管理‘ 但从易用性和学习成本上考虑,shiro更具优势,同时shiro支持和很多接口集成 用户及权限管理是众多 ...
- AFNetworking 3.0 源码解读(十)之 UIActivityIndicatorView/UIRefreshControl/UIImageView + AFNetworking
我们应该看到过很多类似这样的例子:某个控件拥有加载网络图片的能力.但这究竟是怎么做到的呢?看完这篇文章就明白了. 前言 这篇我们会介绍 AFNetworking 中的3个UIKit中的分类.UIAct ...
- 深入理解CSS六种颜色模式
前面的话 赏心悦目的颜色搭配让人感到舒服,修改元素颜色的功能让人趋之若鹜.但颜色规划不当,会让网站用户无所适从.颜色从<font color="">发展至今,保留了很多 ...
- spring boot 实战:我们的第一款开源软件
在信息爆炸时代,如何避免持续性信息过剩,使自己变得专注而不是被纷繁的信息所累?每天会看到各种各样的新闻,各种新潮的技术层出不穷,如何筛选出自己所关心的? 各位看官会想,我们是来看开源软件的,你给我扯什 ...
- Struts2入门(五)——OGNL和标签库
一.前言 OGNL和标签库的作用,粗暴一点说,就是减少在JSP页面中出现java代码,利于维护. 1.1.OGNL 1.1.1.什么是OGNL? OGNL(Object-Graph Navigatio ...
- 如何区别数据库删除语句drop与delete与truncate?
1.delete:删除数据表中的行(可以删除某一行,也可以在不删除数据表的情况下删除所有行) 删除某一行:delete from 数据表名称 where 列名称=值: 删除所有行:delete*fro ...
- Linux网络属性配置
目录 IP地址分类 如何将Linux主机接入到网络中 网络接口的命名方式 ifcfg系列命令 如何配置主机名 如何配置DNS服务器指向 iproute2系列命令 Linux管理网络服务 永久生效配置路 ...
- 万向节锁(Gimbal Lock)的理解
[TOC] 结论 我直接抛出结论: Gimbal Lock 产生的原因不是欧拉角也不是旋转顺序,而是我們的思维方式和程序的执行逻辑没有对应,也就是说是我们的观念导致这个情况的发生. 他人解释 首先我们 ...