提示6. 如何及何时使用贪婪加载

什么时候你需要使用贪婪加载?

通常在你的程序中你知道对查询到的实体将要进行怎样的操作。

例如,如果你查询一个订单以便为一个客户重新打印,你知道没有组成订单的项目即产品的信息重打印将是不完整的,所以你知道你将需要同时加载这些信息。

这是贪婪加载起作用的一类场景。

如果你知道你需要额外信息,或实体,你可能也会预先加载这些实体(贪婪加载),因为这将省下生在将来的查询。

怎样进行贪婪加载?

与一些普遍存在的错误观念相反,Entity Framework中贪婪加载即可行也易行,你仅使用Include()方法如下这样启动查询即可:

1 var reprint = (from order in ctx.Orders.Include("Items.Product")
2              where order.Customer.Name == "Fred Blogs"
3                 && order.Status == "Unshipped"
4              select order).First();

这个查询意思是,在每个满足查询条件的order中包含其"Items",同时每个Item中也包含其"Product".

这样的结果是,如下代码:

1 foreach (var item in reprint.Items)
2 {
3     Console.WriteLine("\t{0} {1} = ${2}",
4         item.Quantity,
5         item.Product.Name,
6         item.Cost);
7 }
8 Console.WriteLine(reprint.TotalCost);

不再需要新的查询。

注意:

不需要显式 Include("Items") ,对 Include("Items.Product") 的调用会隐式包含Items。

提示7 – 怎么在.NET 3.5 SP1中模拟外键属性

背景

如果你一直关注EF Design Blog这个团队博客,你可能已经看到近期我们宣布了一个用于.NET 4.0中EF的称为FK Associations的特性。

然而在.NET 3.5 SP1中,我们仅支持独立关联。这表示外键列不会做为可用的属性出现在实体中。相反这表示你不得不通过到其它实体的引用来建立关联。

例如,不同于Linq to SQL,下面的写法在EF中不可用:

1 product.CategoryID = 2; 

因为在product实体中没有"CategoryID"这个属性。

你不得不使用类似下面的替换方法:

1 product.Category = ctx.Categories.First(c => c.ID == 2); 

也就是你需要使用Category引用。这意味着你不得不在内存中放置一个Category对象,或者像上面例子那样通过查询获取一个。

不存在一个你可以直接设置CategoryID的属性的问题可能造成很大的麻烦,而这就是我们在.NET 4.0中添加了FK Associations与FK Properties的原因。

这看起来都不错,但Julie Lerman总习惯提醒我,现在正在使用.NET 3.5 SP1的人们怎么办?我们的新特性现在帮不上忙。

所以…

怎样在CategoryID不实际存在的情况下设置它?

这问题是个圈套。你当然实现不了这种想法。

但是你可以使用下面的代码实现同样的效果:

1 product.CategoryReference.EntityKey = new EntityKey("MyContainer.Categories", "ID", 2); 

这看起来有点复杂不是吗?所以让我们拆开分析:

1. 对于每一个像Category一样的引用"xxx",Entity Framework也生成了一个返回EntityReference类型的"xxxReference"属性。(EF中大量使用EntityReference来提供完成像保持关系一致性,及基于EntityKeys的实体查找等操作所需的设施与服务)

2. EntityReference的其中一个属性是EntityKey。当我们希望改变外键的值时我们需要将一个新的EntityKey设置到EntityKey属性。

3. 要创建一个新的EntityKey,我们需要知道如下3条:

1). 我们想要设置给"外键"的值。与前面代码段一致,这个值就是2。

2). 目标Entity所属的EntitySet的完成限定名。在这个例子中,我们的目标是一个Category,我们由"MyContainer.Categories"集来获取Category。

3). 目标实体中主键属性的名称。这个例子中Category的主键为"ID"属性。

很显然这不是你想要在你需要的任何地方书写的那种类型的代码。所以我们以这种方式来封装。以便…

怎样使用这些代码来仿造一个外键属性?

幸运的是Entity Framework为实体生成了部分类,所以你可以像这样简单的将这些逻辑放置于你自己的Product部分类中:

 1 public int CategoryID { 2     get {3         if (this.CategoryReference.EntityKey == null) return 0;4         else return (int) this.CategoryReference 5             .EntityKey.EntityKeyValues[0].Value; 6     } 7     set { 8         this.CategoryReference.EntityKey  9            = new EntityKey("MyContainer.Categories", "ID", value);
10     }
11 }

注意我们在get访问器中也使用了CategoryReference。这样我们的CategoryID属性仅就是一个基于CategoryReference的视图,这样如果EF在底层做了任何改变我们也无需被通知。

添加这样的代码后,之前我们想要的写法也就可以实现:

1 product.CategoryID = 2; 

这在做法在很多场景中都特别有用,例如MVC控制器与数据绑定中。

外传

这种解决方案本质上仅仅是隐藏了独立关联的一些限制的变通方案,同所有的变通方案其也存在缺陷。关键就是在优点与缺陷之间做出全面的权衡。一些关键的缺陷如下:

1. 部分类中的属性不会被Entity Framework所识别,所以你不能在LINQ查询中使用它们。

2. 由于在setter访问器中我们通过完全限定名引用了EntitySet,我们将Entity Class与EntitySet直接耦合在一起。对于大多数人这不成问题,但是当你试图在不同上下文间重用你的实体类型或使用MEST(MultipleEntitySets per Type)时这种方法不会工作。

3. 可能还有更多缺陷…当想到它们时我将陆续添加!

提示8 – 怎样使用LINQ to Entities编写"WHERE IN"形式的查询

想象你有一个人员表,你想查询其中姓氏包含于一个有趣的姓氏列表中的那部分人。在SQL中这很平常,你编写这样的查询:

1 SELECT * FROM People
2 WHERE Firstname IN ('Alex', 'Colin', 'Danny', 'Diego') 

SQL中的IN等价于LINQ中的Contains

在LINQ(to objects)的世界不存在'IN',所以你需要像倒置顺序那样来使用Contains方法:

1 var names = new string[] { "Alex", "Colin", "Danny", "Diego" };
2 var matches = from person in people
3         where names.Contains(person.Firstname)
4         select person;

注意语义上我们已经由SQL中的:

value.IN(set)

变为LINQ中的

set.Contains(value)

结果是相同的。

.NET 3.5 SP1与.NET 4.0对Contains的支持

在.NET 4.0的EF中将支持 IEnumerable<T>.Contains(T t) 方法,所以在下个版本EF中你可以编写上文LINQ查询那样的查询。

不幸的是这种写法不被.NET 3.5 SP1支持:当遇到这种形式的LINQ表达式时LINQ to Entities会报错,因为其不知道怎样将对Contains的调用转换为SQL。

但是我们.NET 3.5 SP1的用户怎么办呢?他们应该怎样做?

.NET 3.5 SP1的变通方案

有一个由EF团队"大脑"之一Colin提供的变通方案。

这种变通方案的本质是你可以以如下方式来重写上面的查询:

1 var matches = from person in people
2         where person.Firstname == "Alex" ||
3               person.Firstname == "Colin" ||
4               person.Firstname == "Danny" ||
5               person.Firstname == "Diego"
6         select person;

当然这会使代码变长且编写这样的代码是痛苦的,但是它同样可以工作。

所以如果有一些工具方法可以很容易的创建这种类型的LINQ表达式,我们将很好的处理业务

而恰巧不久之前Colin在论坛上给出了他完成的帮助方法,借助他的方法,你可以如下这样编写查询:

1 var matches = ctx.People.Where(
2         BuildOrExpression<People, string>(
3            p => p.Firstname, names
4         )
5 );

这会生成一个与下面语句相同效果的查询:

1 var matches = from p in ctx.People
2         where names.Contains(p.Firstname)
3         select p;

但事实上后者一个明显的问题是其不可以在.NET 3.5 SP1下工作。

外传

如果你已经阅读至此,很好!

下面是使变通写法成为可能的功能函数:

 1 public static Expression<Func<TElement, bool>> BuildOrExpression<TElement, TValue>( 2         Expression<Func<TElement, TValue>> valueSelector,  3         IEnumerable<TValue> values 4     ) 5 {      6     if (null == valueSelector)  7         throw new ArgumentNullException("valueSelector");8     if (null == values) 9         throw new ArgumentNullException("values");
10     ParameterExpression p = valueSelector.Parameters.Single();
11     if (!values.Any())
12         return e => false;
13     var equals = values.Select(value =>
14         (Expression)Expression.Equal(
15              valueSelector.Body,
16              Expression.Constant(
17                  value,
18                  typeof(TValue)
19              )
20         )
21     );
22    var body = equals.Aggregate<Expression>(
23             (accumulate, equal) => Expression.Or(accumulate, equal)
24     );
25
26    return Expression.Lambda<Func<TElement, bool>>(body, p);
27 }

此函数本质上构造了一个针对所有使用 valueSelector (i.e. p => p.Firstname) 的值断言表达式,并将这些断言进行OR连接来为这个完整的预言创建一个表达式,除此之外,我不打算试图解释这个函数。

转载于:https://www.cnblogs.com/sylone/p/6094548.html

Entity Framework技巧系列之二 - Tip 6 - 8相关推荐

  1. Entity Framework技巧系列之十一 - Tip 42 - 45

    提示42. 怎样使用Code-Only创建一个动态模型 背景: 当我们给出使用Code-Only的例子,总是由创建一个继承自ObjectContext的强类型的Context开始.这个类用于引导模型. ...

  2. (翻译)Entity Framework技巧系列之一 - Tip 1 - 5

    本系列英文原文出自. 提示1. 在Entity Framework中怎样排序关系(Relationships) 问题: 在Entity Framework论坛中常会看到关于排序相关联项目的问题. 例如 ...

  3. matlab 数值解 期权顶级啊,潮盈期权院高胜率交易技巧系列之二----期权交易策略及基于MATLAB统计套利介绍...

    主题: 高胜率交易技巧系列之二----期权交易策略及基于MATLAB统计套利介绍 会场流程: 13:30--14:00:参会嘉宾到场签名 14:00--14:45:期权知识 14:45--15:·25 ...

  4. Entity Framework技术系列之1:数据访问技术概述

    前言 .NET Framework自2002年发布以来,已经历了十来个年头.相应的,.NET平台上的数据访问技术也在不断发展,从最基础的ADO.NET,到SqlHelper简单帮助类,到DAAB(Da ...

  5. 采用EntityFramework.Extended 对EF进行扩展(Entity Framework 延伸系列2)

    前言 今天我们来讲讲EntityFramework.Extended 首先科普一下这个EntityFramework.Extended是什么,如下: 这是一个对Entity Framework进行扩展 ...

  6. 原版98启动盘镜像.img_装机技巧系列(二):系统安装之Windows 10启动盘制作

    在第一期的<用U盘制作自己的PE工具箱>结束之后,原本第二节更新系统安装的几种方法,而将制作Windows 10启动盘作为其中一部分,但最终还是决定单独再写一期制作Windows 10启动 ...

  7. Entity Framework 实践系列 —— 搞好关系 - 单相思(单向一对一,one-to-one)

    原以为躲入代码世界,就可以不用搞关系,哪知"关系无处不在".写代码多年之后,终于明白"面向对象的关键是搞好对象之间的关系".而Entity Framework作 ...

  8. Entity Framework技术系列之2:三种开发模式实现数据访问

    前言 Entity Framework支持Database First.Model First和Code Only三种开发模式,各模式的开发流程大相径庭,开发体验完全不一样.三种开发模式各有优缺点,对 ...

  9. Entity Framework Core系列教程-25-Entity Framework Core日志

    Entity Framework Core日志 我们经常需要在EF Core中记录SQL并更改跟踪信息以进行调试. EF Core日志记录自动与.NET Core的日志记录机制集成.因此,在隐含使用E ...

最新文章

  1. NSDictionary所有API的学习。
  2. 应用程序连接Oracle rac的URL写法
  3. Getting Started With Hazelcast 读书笔记(第七章)
  4. make、make是什么??
  5. 赛我 v.s Fzone v.s 喔赛 用户体验对比分析
  6. 空调微型计算机控制,空调自动控制
  7. C++基础教程之字符串
  8. redis在window下的启动
  9. MyEclipse常用插件使用教程
  10. java中如何写前端代码怎么写_如何编写规范的、可维护的前端代码?
  11. VIIRS-NPP夜光遥感数据下载
  12. 「HenCoder Plus」Android 高级培养计划 FAQ
  13. 透过安全事件看软件组成分析SCA
  14. 测量员软件测试版,测量员app
  15. 不仅仅是游戏,王者荣耀如何突破次元壁?
  16. 迷你星球java,如何用手机制作迷你星球?迷你星球制作方法演示
  17. 原生js实现简易版消消乐
  18. java 排名算法_排行榜的算法
  19. c语言程序判断一个字符串是否是回文数,详解判断回文字符串和回文数算法的C语言代码!...
  20. 10张图了解UWB技术的工作原理

热门文章

  1. 字节是微型计算机中存储容量的度量单位,微型计算机内存容量的基本计量单位...
  2. java vo转map_Jython:在 Java 程序里运行 Python 代码 4.5
  3. anaconda 怎么安装xlrd_Anaconda 安装 tensorflow 和 keras
  4. android 恢复短信 失败,解决安卓手机发送短信失败的方法
  5. linux中firefox替换,Ubuntu更换Firefox版本的方法
  6. 计算机组成与设计第五版英文_南京大学计算机考研信息汇总
  7. access游戏库不显示 ea_英伟达上线云游戏服务 千款游戏月费4.99美元
  8. 显示农历天气时钟小部件下载_安卓最强桌面小部件:Zooper Widget
  9. linux weblogic10 安装,linux 静默安装weblogic10.36
  10. matlab 第二类边界条件,第二类边界条件.ppt