Entity Framework 6 Recipes 2nd Edition(11-5)译 -> 从”模型定义”函数返回一个匿名类型

11-5. 从”模型定义”函数返回一个匿名类型

问题

想创建一个返回一个匿名类型的”模型定义”函数

解决方案

假设已有游客(Visitor) 预订(reservation)房间(hotel ) 的模型,如Figure 11-5所示.

Figure 11-5. A model for hotel reservations

想要返回每位游客房间预订条数和带来的总收入.因为很多地方需要这些信息,所以想要创建一个”模型定义”函数,接受一个查询参数,返回一个包含游客合计信息的匿名类型的集合:

2. 把Listing 11-9 中的代码,插入到.edmx文件的概念模型里<Schema> 标签下,这样我们就定义好了函数.

Listing 11-9. The VisitorSummary() Model-Defined Function

<Function Name="VisitorSummary">

<Parameter Name="StartDate" Type="Edm.DateTime" />

<Parameter Name="Days" Type="Edm.Int32" />

<ReturnType>

<CollectionType>

<RowType>

<Property Name="Name" Type="Edm.String" />

<Property Name="TotalReservations" Type="Edm.Int32" />

<Property Name="BusinessEarned" Type="Edm.Decimal" />

</RowType>

</CollectionType>

</ReturnType>

<DefiningExpression>

Select

r.Visitor.Name,

COUNT(r.ReservationId) as TotalReservations,

SUM(r.Cost) as BusinessEarned

from EFRecipesEntities.Reservations as r

where r.ReservationDate between StartDate and

AddDays(StartDate,Days)

group by r.Visitor.Name

</DefiningExpression>

</Function>

3. 接下来插入和查询模型,代码如 Listing 11-10所示:.

Listing 11-10. Querying the Model Using the VistorySummary() Model-Defined Function

class Program

{

static void Main(string[] args)

{

RunExample();

}

static void RunExample()

{

using (var context = new EFRecipesEntities())

{

var hotel = new Hotel { Name = "Five Seasons Resort" };

var v1 = new Visitor { Name = "Alex Stevens" };

var v2 = new Visitor { Name = "Joan Hills" };

var r1 = new Reservation

{

Cost = 79.99M,

Hotel = hotel,

ReservationDate = DateTime.Parse("2/19/2010"),

Visitor = v1

};

var r2 = new Reservation

{

Cost = 99.99M,

Hotel = hotel,

ReservationDate = DateTime.Parse("2/17/2010"),

Visitor = v2

};

var r3 = new Reservation

{

Cost = 109.99M,

Hotel = hotel,

ReservationDate = DateTime.Parse("2/18/2010"),

Visitor = v1

};

var r4 = new Reservation

{

Cost = 89.99M,

Hotel = hotel,

ReservationDate = DateTime.Parse("2/17/2010"),

Visitor = v2

};

context.Hotels.Add(hotel);

context.SaveChanges();

}

using (var context = new EFRecipesEntities())

{

Console.WriteLine("Using eSQL...");

var esql = @"Select value v from

EFRecipesModel.VisitorSummary(DATETIME‘2010-02-16 00:00‘, 7) as v";

var objectContext = (context as IObjectContextAdapter).ObjectContext;

var visitors = objectContext.CreateQuery<DbDataRecord>(esql);

foreach (var visitor in visitors)

{

Console.WriteLine("{0}, Total Reservations: {1}, Revenue: {2:C}",

visitor["Name"], visitor["TotalReservations"],

visitor["BusinessEarned"]);

}

}

using (var context = new EFRecipesEntities())

{

Console.WriteLine();

Console.WriteLine("Using LINQ...");

//译注:在我的EF6.1.1.3下,这句查询会出现异常

var visitors = from v in

context.VisitorSummary(DateTime.Parse("2/16/2010"), 7)

select v;

foreach (var visitor in visitors)

{

Console.WriteLine("{0}, Total Reservations: {1}, Revenue: {2:C}",

visitor["Name"], visitor["TotalReservations"],

visitor["BusinessEarned"]);

}

}

}

}

partial class EFRecipesEntities

{

[EdmFunction("EFRecipesModel", "VisitorSummary")]

public IQueryable<DbDataRecord> VisitorSummary(DateTime StartDate, int Days)

{

var objectContext = (this as IObjectContextAdapter).ObjectContext;

return objectContext.CreateQuery<DbDataRecord>(

Expression.Call(Expression.Constant(this),

(MethodInfo)MethodInfo.GetCurrentMethod(),

new Expression[] { Expression.Constant(StartDate),

Expression.Constant(Days) }

).ToString());

}

}

上面Listing 11-10 的代码输出如下:

Using eSQL...

Alex Stevens, Total Reservations: 2, Revenue: $189.98

Joan Hills, Total Reservations: 2, Revenue: $189.98

Using LINQ...

Alex Stevens, Total Reservations: 2, Revenue: $189.98

Joan Hills, Total Reservations: 2, Revenue: $189.98

它是如何工作的?

在Listing 11-9里, 在VisitorSummary() 函数定义里,我们按实体的导航属性visitor进行分组,我们用eSQL Count() 的 函数计算每位游客的预订房间数量,用Sum() 把每位游客付的租金合计.

在这个函数里,我们把结果组织成:: Name, TotalReservations, 和BusinessEarned. 此处我们使用了<CollectionType> 和<RowType> 标签来指明返回类型. 在运行时里,用包含DbDataRecords的集合

为了使该函数能在LINQ查询中使用,我们创建了运行时方法(返回IQueryable<DbDataRecord>.) .和前面的小节一样,我们用EdmFunction()特性修饰该方法.. 因为需要返回一个IQueryable<T>, 所以我们需要在这个方法体中包含函数调用,以便它能用在查询表达式树中.

此外,我们需要在ObjectContext中访问QueryProvider来返回一个IQueryable<T>,所以我们需要在EFRecipesEntities类中实现这个方法.

附:创建示例用到的数据库的脚本文件

时间: 2024-11-07 00:57:31

Entity Framework 6 Recipes 2nd Edition(11-5)译 -> 从”模型定义”函数返回一个匿名类型的相关文章

Entity Framework 6 Recipes 2nd Edition(11-1)译 -&gt; 从“模型定义”函数返回一个标量值

第11章函数 函数提供了一个有力代码复用机制, 并且让你的代码保持简洁和易懂. 它们同样也是EF运行时能利用的数据库层代码.函数有几类: Rowset Functions, 聚合函数, Ranking Functions, 和标量值函数. 函数要么确定,要么不确定.当用一些指定的值调用函数,而函数返回的结果总是一样时,它就是确定的函数.当甚至用同样的一些值调用时,而函数每次返回的结果也可能不一样,它就是不确定的函数. 在前七小节,我们探讨“模型定义”的函数,这些函数允许我们在概念层上创建.这些函

Entity Framework 6 Recipes 2nd Edition(11-2)译 -&gt; 为一个”模型定义”函数返回一个计算列

11-3. 为一个”模型定义”函数返回一个计算列 问题 想从”模型定义”函数里返回一个计算列 解决方案 假设我们有一个员工(Employee)实体,属性有: FirstName, LastName,和BirthDate, 如 Figure 11-3所示. Figure 11-3. An Employee entity with a few typical properties 我们想要创建一个”模型定义”函数,让它返回FirstName 和LastName 合并后的full name . 我们想

Entity Framework 6 Recipes 2nd Edition(10-4)译 -&gt; 从存储过程返回一个复杂类型

10-4. 从存储过程返回一个复杂类型 问题 想在方法中使用一个返回复杂类型的存储过程 解决方案 假设我们已经有如Figure 10-3.所示的模型,该Employee (雇员)模型包含EmployeeId,Name和一个复杂类型的Address属性,Address包含Employee地址信息:它是包含city, state, 和ZIP code的复杂类型EmployeeAddress Figure 10-3. 一个Employee entity实体含有一个名为EmployeeAddress 复

Entity Framework 6 Recipes 2nd Edition(9-3)译-&gt;找出Web API中发生了什么变化

9-3. 找出Web API中发生了什么变化 问题 想通过基于REST的Web API服务对数据库进行插入,删除和修改对象图,而不必为每个实体类编写单独的更新方法. 此外, 用EF6的Code Frist实现数据访问管理. 本例,我们模拟一个N层场景,用单独的客户端(控制台应用)来调用单独的基于REST服务的Web网站(WEB API应用) . 注意:每层使用单独的Visual Studio 解决方案, 这样更方便配置.调试和模拟一个N层应用. 假设有一个如Figure 9-3所示的旅行社和预订

Entity Framework 6 Recipes 2nd Edition(9-4)译-&gt;Web API 的客户端实现修改跟踪

9-4. Web API 的客户端实现修改跟踪 问题 我们想通过客户端更新实体类,调用基于REST的Web API 服务实现把一个对象图的插入.删除和修改等数据库操作.此外, 我们想通过EF6的Code First方式实现对数据的访问. 本例,我们模拟一个N层场景,用单独的控制台应用程序作为客户端,调用Web API服务(web api项目). 注:每个层用一个单独的解决方案,这样有助于调试和模拟N层应用. 解决方案 假设我们一个如Figure 9-4.所示模型 Figure 9-4. A 客户

Entity Framework 6 Recipes 2nd Edition(目录索引)

Chapter01. Getting Started with Entity Framework / 实体框架入门 1-1. A Brief Tour of the Entity Framework World / 简单浏览实体框架世界 goto1-2. Using Entity Framework / 使用实体框架 Chapter02. Entity Data Modeling Fundamentals / 实体数据建模基础 2-1. Creating a Simple Model2-2. C

Entity Framework 6 Recipes 2nd Edition(13-3)译 -&gt; 为一个只读的访问获取实体

问题 你想有效地获取只是用来显示不会更新的操作的实体.另外,你想用CodeFirst的方式来实现 解决方案 一个非常常见行为,尤其是网站,就是只是让用户浏览数据.大多数情况下,用户不会更新数据.在这种情况下,你可以通过避开上下文的缓存和修改跟踪来提高代码性能,你可以非常简单地使用AsNoTracking方法来实现. 让我们假设你一个应用程序来管理doctor(医生)的appointments(预约),你的模型如下图Figure 13-5. Figure 13-5. A model for man

Entity Framework 6 Recipes 2nd Edition(13-4)译 -&gt; 有效地创建一个搜索查询

问题 你想用LINQ写一个搜索查询,能被转换成更有效率的SQL.另外,你想用EF的CodeFirst方式实现. 解决方案 假设你有如下Figure 13-6所示的模型 Figure 13-6. A simple model with a Reservation entity            首先,这个例子用EF的CodeFirst方式实现,在Listing 13-10,我们创建实体类Reservation Listing 13-10. The Reservation Entity Obje

Entity Framework 6 Recipes 2nd Edition(13-2)译 -&gt; 用实体键获取一个单独的实体

问题 不管你用DBFirst,ModelFirst或是CodeFirst的方式,你想用实体键获取一个单独的实体.在本例中,我们用CodeFirst的方式. 解决方案 假设你有一个模型表示一个Painting(绘画)类型的实体,如Figure 13-2所示: Figure 13-2. The Painting entity type in our model 在代码In Listing 13-2,我们创建实体类Painting. public class Painting { public str