11-4.在”模型定义”函数里调用另一个”模型定义”函数

问题

想要用一个”模型定义”函数去实现另一个”模型定义”函数

解决方案

假设我们已有一个公司合伙人关系连同它们的结构模型,如Figure 11-4所示:

Figure 11-4. A model representing the associate types in a company together with the reporting association

在我们的虚拟的公司里, , team members被一个team leader管理. Team leaders 被 project Managers管理. 而Supervisors管理 project managers.

如果我们想从给定的一个project manager 或supervisor返回所有他们管理的team members ,我们将需要通过  project managers 和team leaders才能获取到 team members. 为了隐藏导航透过这些层的复杂性,我们可以创建”模型定义”函数,来更简单地和直接地访问这些导航属性:

1. 在解决方案资源管理中右击.edmx 文件,打开方式 ➤ XML 编辑器.

2.把Listing 11-7 里的代码插入到概念层的<Schema> 标签下,这样就定义好了函数

Listing 11-7. Model-Defined Functions for Navigating the Associate Hierarchy

<Function Name="GetProjectManager" ReturnType="EFRecipesModel1104.ProjectManager">

<Parameter Name="teammember" Type="EFRecipesModel1104.TeamMember" />

<DefiningExpression>

treat(teammember.Manager.Manager as EFRecipesModel1104.ProjectManager)

</DefiningExpression>

</Function>

<Function Name="GetSupervisor" ReturnType="EFRecipesModel1104.Supervisor">

<Parameter Name="teammember" Type="EFRecipesModel1104.TeamMember" />

<DefiningExpression>

treat(EFRecipesModel1104.GetProjectManager(teammember).Manager as

EFRecipesModel1104.Supervisor)

</DefiningExpression>

</Function>

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

Listing 11-8. Using Both eSQL and LINQ to Query the Model

class Program

{

static void Main(string[] args)

{

RunExample();

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

Console.ReadKey();

}

static void RunExample()

{

using (var context = new EFRecipesEntities1104())

{

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

var john = new Supervisor { Name = "John Smith" };

var steve = new Supervisor { Name = "Steve Johnson" };

var jill = new ProjectManager

{

Name = "Jill Masterson",

Manager = john

};

var karen = new ProjectManager

{

Name = "Karen Carns",

Manager = steve

};

var bob = new TeamLead { Name = "Bob Richardson", Manager = karen };

var tom = new TeamLead { Name = "Tom Landers", Manager = jill };

var nancy = new TeamMember { Name = "Nancy Jones", Manager = tom };

var stacy = new TeamMember

{

Name = "Stacy Rutgers",

Manager = bob

};

context.Associates.Add(john);

context.Associates.Add(steve);

context.SaveChanges();

}

using (var context = new EFRecipesEntities1104())

{

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

var emps = context.Associates.OfType<TeamMember>()

//译注:这个where是下载的源码用的形式,但它怎么看也不是eSQL

.Where(q => q.Manager.Name == "Jill Masterson" || q.Manager.Name == "Steve Johnson");

//译注:这个where里书里的代码,倒像eSQL,可是找不到Where这个形式的重载,可能在某个扩展包里,有知晓,望赐教!

//                .Where(@"EFRecipesModel1104.GetProjectManager(it).Name = @projectManager ||

//EFRecipesModel.GetSupervisor(it).Name == @supervisor",

//                new ObjectParameter("projectManager", "Jill Masterson"),

//                new ObjectParameter("supervisor", "Steve Johnson"));

Console.WriteLine("Team members that report up to either");

Console.WriteLine("Project Manager Jill Masterson ");

Console.WriteLine("or Supervisor Steve Johnson");

foreach (var emp in emps)

{

Console.WriteLine("\tAssociate: {0}", emp.Name);

}

}

using (var context = new EFRecipesEntities1104())

{

Console.WriteLine();

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

var emps = from e in context.Associates.OfType<TeamMember>()

where MyFunctions.GetProjectManager(e).Name ==

"Jill Masterson" ||

MyFunctions.GetSupervisor(e).Name == "Steve Johnson"

select e;

Console.WriteLine("Team members that report up to either");

Console.WriteLine("Project Manager Jill Masterson ");

Console.WriteLine("or Supervisor Steve Johnson");

foreach (var emp in emps)

{

Console.WriteLine("\tAssociate: {0}", emp.Name);

}

}

}

}

public class MyFunctions

{

[EdmFunction("EFRecipesModel1104", "GetProjectManager")]

public static ProjectManager GetProjectManager(TeamMember member)

{

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

}

[EdmFunction("EFRecipesModel1104", "GetSupervisor")]

public static Supervisor GetSupervisor(TeamMember member)

{

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

}

}

上述Listing 11-8 代码输出如下:

Using eSQL...

Team members that report up to either

Project Manager Jill Masterson

or Supervisor Steve Johnson

Associate: Nancy Jones

Associate: Stacy Rutgers

Using LINQ...

Team members that report up to either

Project Manager Jill Masterson

or Supervisor Steve Johnson

Associate: Nancy Jones

Associate: Stacy Rutgers

它是如何工作的?

在如Listing 11-7所示的GetSupervisor() 函数中,我们需要做给 Manager 属性做三次导航.第一次从TeamMember导航到TeamLead, 第二次从TeamLead,导航到ProjectManager,最后一次从ProjectManager导航到Supervisor. 在Listing 11-7中,我们也定义了GetProjectManager() 函数,所以我们可以用这个函数来简化GetSupervisor() 函数.

我们使用eSQL的treat()运算符把一个公司合伙人实例转化为它们正确的类型 (ProjectManager 或Supervisor). 如果不使用这个运算符,EF将引发一个异常(不能遇到将Associate 映射为ProjectManager 或Supervisor)

在Listing 11-8中, 用 GetProjectManager() 和GetSupervisor() 函数,可以使我们的代码简洁些,因为隐藏了所有通过Manager导航属性穿越对象图的细节

因为我们函数不是返回一个IQueryable<T>, 所以我们不必为LINQ查询实现运行时方法,只需要用到它们的方法存根.

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

Entity Framework 6 Recipes 2nd Edition(11-4)译 -> 在”模型定义”函数里调用另一个”模型定义”函数的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  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 ...

  10. Entity Framework 6 Recipes 2nd Edition(13-5)译 -> 使POCO的修改追踪更高

    问题 你正在使用POCO,你想提高修改跟踪的性能,同时使内存消耗更少.另外,你想通过EF的CodeFirst方式来实现. 解决方案 假设你有一个关于Account(帐户)和相关的Payments(支付 ...

随机推荐

  1. C语言 · 高精度加法

    问题描述 输入两个整数a和b,输出这两个整数的和.a和b都不超过100位. 算法描述 由于a和b都比较大,所以不能直接使用语言中的标准数据类型来存储.对于这种问题,一般使用数组来处理. 定义一个数组A ...

  2. 数学思想:为何我们把 x²读作x平方

    要弄清楚这个问题,我们得先认识一个人.古希腊大数学家 欧多克索斯,其在整个古代仅次于阿基米德,是一位天文学家.医生.几何学家.立法家和地理学家. 为何我们把 x²读作x平方呢? 古希腊时代,越来越多的 ...

  3. ASP.NET Core 中文文档 第四章 MVC(3.8)视图中的依赖注入

    原文:Dependency injection into views 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:孟帅洋(书缘) ASP.NET Core 支持在视图中使用 依赖 ...

  4. [原]CentOS7.2部署node-mapnik

    转载请注明表作者think8848及出处(http://think8848.cnblogs.com) node-mapnik依赖项中要求g++ >= 5, toolchain (>= GL ...

  5. 微软.NET Core RC2正式发布,横跨所有平台

    .NET官方博客宣布了<Announcing .NET Core RC2 and .NET Core SDK Preview 1>,正式如期发布了.NET Core RC2, 现在可以放心 ...

  6. ASP.NET Core框架揭秘(持续更新中…)

    之前写了一系列关于.NET Core/ASP.NET Core的文章,但是大都是针对RC版本.到了正式的RTM,很多地方都发生了改变,所以我会将之前发布的文章针对正式版本的.NET Core 1.0进 ...

  7. javascript:逆波兰式表示法计算表达式结果

    逆波兰式表示法,是由栈做基础的表达式,举个例子: 5 1 2 + 4 * + 3 -  等价于   5 + ((1 + 2) * 4) - 3 原理:依次将5 1 2 压入栈中, 这时遇到了运算符 + ...

  8. 使用C/C++写Python模块

    最近看开源项目时学习了一下用C/C++写python模块,顺便把学习进行一下总结,废话少说直接开始: 环境:windows.python2.78.VS2010或MingW 1 创建VC工程 (1) 打 ...

  9. 玩转spring boot——AOP与表单验证

    AOP在大多数的情况下的应用场景是:日志和验证.至于AOP的理论知识我就不做赘述.而AOP的通知类型有好几种,今天的例子我只选一个有代表意义的“环绕通知”来演示. 一.AOP入门 修改“pom.xml ...

  10. git克隆项目到本地&&全局安装依赖项目&&安装依赖包&&启动服务

     一.安装本地开发环境 1.安装本项目 在需要保存到本地的项目的文件夹,进入到文件夹里点击右键,bash here,出现下图: 2.安装依赖项目  3.安装依赖包(进入到命令行) # 安装依赖包 $ ...