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的方式来实现 解决方案 一个非常常见行为,尤其是网站,就是只是让用户浏览数据.大多数情况下,用户不会更新数据.在这种 ...
随机推荐
- H5单页面手势滑屏切换原理
H5单页面手势滑屏切换是采用HTML5 触摸事件(Touch) 和 CSS3动画(Transform,Transition)来实现的,效果图如下所示,本文简单说一下其实现原理和主要思路. 1.实现原理 ...
- 【详细教程】论android studio中如何申请百度地图新版Key中SHA1值
一.写在前面 现在越来越多的API接口要求都要求提供我们的项目SHA1值,开发版目前还要求不高,但是发布版是必定要求的.而目前定位在各大APP中也较为常见,当下主流的百度地图和高德地图都在申请的时候会 ...
- PHP好用但又容易忽略的小知识
1.PHP函数之判断函数是否存在 当我们创建了自定义函数,并且了解了可变函数的用法,为了确保程序调用的函数是存在的,经常会先使用function_exists判断一下函数是否存在.同样的method_ ...
- Javascript 严格模式详解
转自http://www.ruanyifeng.com/blog/2013/01/javascript_strict_mode.html 一.概述 除了正常运行模式,ECMAscript 5添加了第二 ...
- 微信小程序开发日记——高仿知乎日报(上)
本人对知乎日报是情有独钟,看我的博客和github就知道了,写了几个不同技术类型的知乎日报APP 要做微信小程序首先要对html,css,js有一定的基础,还有对微信小程序的API也要非常熟悉 我将该 ...
- SpringMVC视图解析器
SpringMVC视图解析器 前言 在前一篇博客中讲了SpringMVC的Controller控制器,在这篇博客中将接着介绍一下SpringMVC视 图解析器.当我们对SpringMVC控制的资源发起 ...
- Windows下MySQL无法启动
问题描述: 从网上下了5.7 的MySQL,在bin目录下执行 start mysqld ,弹出个cmd窗口一闪就没了,也看不清是什么报错.mysqld --install安装了服务,也启动不了. ...
- 树莓派3B的食用方法-1(装系统 网线ssh连接)
首先要有一个树莓派3B , 在某宝买就行, 这东西基本上找到假货都难,另外国产和英国也没什么差别,差不多哪个便宜买哪个就行. 不要买店家的套餐,一个是配的东西有些不需要,有的质量也不好. 提示:除了G ...
- github入门到上传本地项目【网上资源整合】
[在原文章的基础上,修改了描述的不够详细的地方,对内容进行了扩充,整合了网上的一些资料] [内容主要来自http://www.cnblogs.com/specter45/p/github.html#g ...
- SQL Server2014 SP2关键特性
SQL Server2014 SP2关键特性 转载自:https://blogs.msdn.microsoft.com/sqlreleaseservices/sql-2014-service-pack ...