11-3. 为一个”模型定义”函数返回一个计算列

问题

想从”模型定义”函数里返回一个计算列

解决方案

假设我们有一个员工(Employee)实体,属性有: FirstName, LastName,和BirthDate, 如

Figure 11-3所示.

Figure 11-3. An Employee entity with a few typical properties

我们想要创建一个”模型定义”函数,让它返回FirstName 和LastName 合并后的full name

. 我们想要创建另一个”模型定义”函数,让它返回根据BirthDate 列计算出的age

按以下操作:

1. 右击解决方案中的.edmx 文件, 打开方式 ➤ XML 编辑器.

2. 把 Listing 11-5 里的代码插入到.edmx文件的概念模型节点的<Schema> 标签下.这样就在模型里定义好了函数.

Listing 11-5. Code for Model-Defined Functions

<Function Name="FullName" ReturnType="Edm.String">

<Parameter Name="emp" Type="EFRecipesModel1103.Employee" />

<DefiningExpression>

Trim(emp.FirstName) + " " + Trim(emp.LastName)

</DefiningExpression>

</Function>

<Function Name="Age" ReturnType="Edm.Int32">

<Parameter Name="emp" Type="EFRecipesModel1103.Employee" />

<DefiningExpression>

Year(CurrentDateTime()) - Year(emp.BirthDate)

</DefiningExpression>

</Function>

3. 插入和查询模型的代码,如Listing 11-6所示的代码:.

Listing 11-6. 用eSQL 和LINQ两种方式调用(“模型定义”函数)来查询模型

class Program

{

static void Main(string[] args)

{

RunExample();

Console.WriteLine("\nPress any key to exit...");

Console.ReadKey();

}

static void RunExample()

{

using (var context = new EFRecipesEntities1103())

{

context.Database.ExecuteSqlCommand("delete from chapter11.employee");

context.Employees.Add(new Employee

{

FirstName = "Jill",

LastName = "Robins",

Birthdate = DateTime.Parse("3/2/1976")

});

context.Employees.Add(new Employee

{

FirstName = "Michael",

LastName = "Kirk",

Birthdate = DateTime.Parse("4/12/1985")

});

context.Employees.Add(new Employee

{

FirstName = "Karen",

LastName = "Stanford",

Birthdate = DateTime.Parse("7/6/1963")

});

context.SaveChanges();

}

using (var context = new EFRecipesEntities1103())

{

Console.WriteLine("Query using eSQL");

var esql = @"Select EFRecipesModel1103.FullName(e) as Name,

EFRecipesModel1103.Age(e) as Age from

EFRecipesEntities1103.Employees as e";

var objectContext = (context as IObjectContextAdapter).ObjectContext;

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

foreach (var emp in emps)

{

Console.WriteLine("Employee: {0}, Age: {1}", emp["Name"],emp["Age"]);

}

}

using (var context = new EFRecipesEntities1103())

{

Console.WriteLine("\nQuery using LINQ");

var emps = from e in context.Employees

select new

{

Name = MyFunctions.FullName(e),

Age = MyFunctions.Age(e)

};

foreach (var emp in emps)

{

Console.WriteLine("Employee: {0}, Age: {1}", emp.Name,  emp.Age.ToString());

}

}

}

}

public class MyFunctions

{

[EdmFunction("EFRecipesModel1103", "FullName")]

public static string FullName(Employee employee)

{

throw new NotSupportedException("Direct calls are not supported.");

}

[EdmFunction("EFRecipesModel1103", "Age")]

public static int Age(Employee employee)

{

throw new NotSupportedException("Direct calls are not supported.");

}

}

上述Listing 11-6执行结果如下:

Query using eSQL

Employee: Jill Robins, Age: 37

Employee: Michael Kirk, Age: 28

Employee: Karen Stanford, Age: 50

Query using LINQ

Employee: Jill Robins, Age: 37

Employee: Michael Kirk, Age: 28

Employee: Karen Stanford, Age: 50

它是如何工作的?

我们的”模型定义”函数FullName()返回的是Edm.String类型, Age()返回的是Edm.Int32.这些函数定义在概念层,所以它们不直接引用实体数据模型系统以外的类型. 这些原始的类型容易转化为运行时系统的类型.

在 <DefiningExpression> 里或”模型定义”函数的函数体里,我们直接访问参数接收到的实体的属性.这里没必要用select 语句. 然后,结果表达式必须要有一个类型来匹配函数返回的类型.

在插入一些employee到我们的模型之后,我们的第一个查询用 eSQL. 我们构造一个eSQL 表达式来调用我们的两个”模型定义”函数,并且把结果投射到 Name 和Age列  . 我们的 eSQL 表达式的结果为一个包含Name和Age成员的匿名类型的集合.因为我们不是返回一个在模型里定义好的类型, 所以我们CreateQuery<T>()中的类型声明为DbDataRecord.然后我们遍历查询结果集,并把所有employee的name和age打印出来

在 LINQ 查询里, 我们从Employee实体集中检索,正如本章前面章节一样, .因为我们返回的也是一个标量值,所以我们需要定义一个相应的运行时方法.这些方法只是利用它的签名而不会被调用.

我们可以在Employee实体中为计算所得的full name 和age分别声明只读的属性,然而这样会使得这些计算在实体被取回时都要进行,但我们用”模型定义”函数,只有在我们需要用到这些属性时才进行计算

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

Entity Framework 6 Recipes 2nd Edition(11-2)译 -> 为一个”模型定义”函数返回一个计算列的更多相关文章

  1. Entity Framework 6 Recipes 2nd Edition 译 -> 目录 -持续更新

    因为看了<Entity Framework 6 Recipes 2nd Edition>这本书前面8章的翻译,感谢china_fucan. 从第九章开始,我是边看边译的,没有通读,加之英语 ...

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

    第11章函数 函数提供了一个有力代码复用机制, 并且让你的代码保持简洁和易懂. 它们同样也是EF运行时能利用的数据库层代码.函数有几类: Rowset Functions, 聚合函数, Ranking ...

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

    9-3. 找出Web API中发生了什么变化 问题 想通过基于REST的Web API服务对数据库进行插入,删除和修改对象图,而不必为每个实体类编写单独的更新方法. 此外, 用EF6的Code Fri ...

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

    9-4. Web API 的客户端实现修改跟踪 问题 我们想通过客户端更新实体类,调用基于REST的Web API 服务实现把一个对象图的插入.删除和修改等数据库操作.此外, 我们想通过EF6的Cod ...

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

    Chapter01. Getting Started with Entity Framework / 实体框架入门 1-1. A Brief Tour of the Entity Framework ...

  6. Entity Framework 6 Recipes 2nd Edition(9-1)译->用Web Api更新单独分离的实体

    第九章 在N层结构的应用程序中使用EF 不是所有的应用都能完全地写入到一个单个的过程中(就是驻留在一个单一的物理层中),实际上,在当今不断发展的网络世界,大量的应用程序的结构包含经典的表现层,应用程, ...

  7. Entity Framework 6 Recipes 2nd Edition(13-2)译 -> 用实体键获取一个单独的实体

    问题 不管你用DBFirst,ModelFirst或是CodeFirst的方式,你想用实体键获取一个单独的实体.在本例中,我们用CodeFirst的方式. 解决方案 假设你有一个模型表示一个Paint ...

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

    问题 你想有效地获取只是用来显示不会更新的操作的实体.另外,你想用CodeFirst的方式来实现 解决方案 一个非常常见行为,尤其是网站,就是只是让用户浏览数据.大多数情况下,用户不会更新数据.在这种 ...

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

    问题 你想用LINQ写一个搜索查询,能被转换成更有效率的SQL.另外,你想用EF的CodeFirst方式实现. 解决方案 假设你有如下Figure 13-6所示的模型 Figure 13-6. A s ...

随机推荐

  1. Jexus 5.8.2 正式发布为Asp.Net Core进入生产环境提供平台支持

    Jexus 是一款运行于 Linux 平台,以支持  ASP.NET.PHP 为特色的集高安全性和高性能为一体的 WEB 服务器和反向代理服务器.最新版 5.8.2 已经发布,有如下更新: 1,现在大 ...

  2. ASP.NET Web API 跨域访问(CORS)

    一.客户端用JSONP请求数据 如果你想用JSONP来获得跨域的数据,WebAPI本身是不支持javascript的callback的,它返回的JSON是这样的: {"YourSignatu ...

  3. Enterprise Solution 3.1 企业应用开发框架 .NET ERP/CRM/MIS 开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    行业:基于数据库的制造行业管理软件,包含ERP.MRP.CRM.MIS.MES等企业管理软件 数据库平台:SQL Server 2005或以上 系统架构:C/S 开发技术 序号 领域 技术 1 数据库 ...

  4. CentOS7 重置root密码

    1- 在启动grub菜单,选择编辑选项启动 2 - 按键盘e键,来进入编辑界面 3 - 找到Linux 16的那一行,将ro改为rw init=/sysroot/bin/sh 4 - 现在按下 Con ...

  5. SDWebImage源码解读 之 NSData+ImageContentType

    第一篇 前言 从今天开始,我将开启一段源码解读的旅途了.在这里先暂时不透露具体解读的源码到底是哪些?因为也可能随着解读的进行会更改计划.但能够肯定的是,这一系列之中肯定会有Swift版本的代码. 说说 ...

  6. [C#] C# 知识回顾 - 序列化

    C# 知识回顾 -  序列化 [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5902005.html 目录 序列化的含义 通过序列化保存对象数据 众 ...

  7. Java进击C#——前言

    本章简言 记得三年前笔者来到现在的公司的时候,公司人口不出十个人.那个时候笔者刚从日本回来,想在福州.厦门.青岛找一个合适自己发展的机会.最后我的一个福州的朋友打电话希望我能过去帮他,跟他一起创业.这 ...

  8. 敏捷软件开发VS传统软件工程

    敏捷软件开发:又称敏捷开发,是一种从1990年代开始逐渐引起广泛关注的一些新兴软件开发方法,是一种应对快速变化的需求的一种软件开发能力. 与传统软件工程相比,它们的具体名称.理念.过程.术语都不尽相同 ...

  9. Linux初识

    在这篇文章中你讲看到如下内容: 计算机的组成及功能: Linux发行版之间的区别和联系: Linux发行版的基础目录及功用规定: Linux系统设计的哲学思想: Linux系统上获取命令帮助,及man ...

  10. 【微信SEO】公众号也能做排名?

    [写于2016年8月] 最近,微信团队发出一则公告,开放公众号运营者一年内更改公众号名一次,这对不少名字起的奇葩名字(包括dkplus)的公众号来说是一件好事. 为什么说是好事呢?公众号名字直接关联到 ...