Entity Framework 4.1 : 贪婪加载和延迟加载
这篇文章将讨论查询结果的加载控制。
EF4.1 允许控制对象之间的关系,当我们进行查询的时候,哪些关系的数据将会被加载到内存呢?所有相关的对象都需要吗?在一些场合可能有意义,例如,当查询的实体仅仅拥有一个相关的子实体,但是,多数情况下,你可能只需要加载部分数据,或者你喜欢的话,加载更多的数据。
默认情况下, EF4.1 仅仅加载查询中涉及的实体,但是它支持两种特性来帮助你控制加载:
- 贪婪加载
- 延迟加载
贪婪加载
对于下面的查询
using (var context =new MyDomainContext())
{ var orders = from o in context.Orders.Include("OrderDetails")
where o.CustomerName =="Mac"
select o;
这里我指定加载某些订单,就是客户名为 Mac 的客户的订单,而且希望相关的订单明细也一起加载。
你可以这样查看实际执行的 SQL 查询
Console.WriteLine(orders.ToString());
实际的 SQL 如下所示:
SELECT
[Project1].[OrderID]AS[OrderID],
[Project1].[OrderTitle]AS[OrderTitle],
[Project1].[CustomerName]AS[CustomerName],
[Project1].[TransactionDate]AS[TransactionDate],
[Project1].[C1]AS[C1],
[Project1].[OrderDetailID]AS[OrderDetailID],
[Project1].[OrderID1]AS[OrderID1],
[Project1].[Cost]AS[Cost],
[Project1].[ItemName]AS[ItemName]
FROM ( SELECT
[Extent1].[OrderID]AS[OrderID],
[Extent1].[OrderTitle]AS[OrderTitle],
[Extent1].[CustomerName]AS[CustomerName],
[Extent1].[TransactionDate]AS[TransactionDate],
[Extent2].[OrderDetailID]AS[OrderDetailID],
[Extent2].[OrderID]AS[OrderID1],
[Extent2].[Cost]AS[Cost],
[Extent2].[ItemName]AS[ItemName],
CASEWHEN ([Extent2].[OrderDetailID]ISNULL) THENCAST(NULLASint) ELS
E 1ENDAS[C1]
FROM[dbo].[Orders]AS[Extent1]
LEFTOUTERJOIN[dbo].[OrderDetails]AS[Extent2]ON[Extent1].[OrderID]
=[Extent2].[OrderID]
WHERE N'Mac'=[Extent1].[CustomerName]
) AS[Project1]
ORDERBY[Project1].[OrderID]ASC, [Project1].[C1]ASC
EF4.1 生成的 SQL 不是特别易读,但是这个查询你应该能够看懂,订单明细被一起加载了。
这带来了一个关于贪婪加载的问题:查询效率。如果你执行这样的查询来获取订单和订单明细,也可以变成写出等效的查询语句,如果喜欢的话,可以更加聪明地写出返回两个查询结果的查询,一个是订单,另外一个是订单明细。这应该更加有效,因为你不需要为每一个订单明细重复订单的信息。由于一些原因,EF 并不支持。记住这一点,因为这很容易使性能变差。
无论如何,你还可以在查询中包含更多的子集。
var orders =from o in context.Orders.Include("OrderDetails").Include("Businesses")
where o.CustomerName == "Mac"
select o;
延迟加载
另外一个特性就是延迟加载,默认情况下,延迟加载被支持,如果你希望禁用它,必须显式声明,最好的位置是在 DbContext 的构造器中。
public MyDomainContext()
{
this.Configuration.LazyLoadingEnabled = false;
}
这样延迟加载就如你所愿了。当查询一个实体集的时候,相关的子实体也一并加载。
当 EF 访问实体的子实体的时候是如何工作的呢?你的集合是 POCO 的集合,所以,在访问的时候没有事件发生,EF 通过从你定义的实体派生一个动态的对象,然后覆盖你的子实体集合访问属性来实现。这就是为什么需要标记你的子实体集合属性为 virtual 的原因。
public class Order
{
publicint OrderID { get; set; }
public string OrderTitle { get; set; }
public string CustomerName { get; set; }
publicDateTime TransactionDate { get; set; }
public virtual List<OrderDetail> OrderDetails { get; set; }
public virtual List<Business> Businesses { get; set; }
}
总结一下两种加载方式的特点
贪婪加载:
- 减少数据访问的延迟,在一次数据库的访问中返回所有的数据。
- 你需要知道你将作什么,并且显式声明
延迟加载:
- 非常宽容,因为只在需要的时候加载数据,不需要预先计划
- 可能因为数据访问的延迟而降低性能,考虑到每访问父实体的子实体时,就需要访问数据库。
现在,什么时候我们应该使用哪种机制?我的建议是:除非需要循环中加载数据,我使用延迟加载。这样的话,可能会造成2-3 次服务器的查询,但是仍然是可以接受的,特别是考虑到贪婪加载的效率问题。
Entity Framework 4.1 : 贪婪加载和延迟加载的更多相关文章
- EF之贪婪加载和延迟加载
这篇文章将讨论查询结果的控制 在使用EF(Entity Framework)的过程中,很多时候我们会进行查询的操作,因此知道哪些数据会被加载到内存当中就至关重要.在多多的情况下,你可能并并不需要加载全 ...
- 【EfF】 贪婪加载和延迟加载 (virtual去掉关闭延迟加载)
EntityFramework(EF)贪婪加载和延迟加载的选择和使用 贪婪加载:顾名思议就是把所有要加载的东西一 次性读取 1 using (var context = new MyDbContext ...
- EF中的贪婪加载和延迟加载(懒加载)
在上一章中,我们使用了Linq对Entity Framework进行了一个查询,但是通过学习我们却发现了懒加载给我来的性能上的开销是很到的,尤其是在循环中,如果数据量不是很多的情况下还可以接受,如果数 ...
- EntityFramework 贪婪加载与延迟加载以及资源回收
EntityFramework的资源回收 1) Using 内包含Entity的上下文关系,对俩表做Add操作,最好可以直接写一个 entity.SaveChanges(); 完成两张表的同时add操 ...
- 学习EF之贪婪加载和延迟加载(1)
从暑假开始接触code first以来,一直感觉很好用,主要在于开发过程中以业务为中心可以随时修改数据模型生成数据库,还有一个原因就是查询起来很方便 这里找了一个以前database first的一段 ...
- 【转】EntityFramework(EF)贪婪加载和延迟加载的选择和使用
原谅:http://www.weixq.cn/Article/Detail/906 贪婪加载:顾名思议就是把所有要加载的东西一 次性读取 using (var context = new MyDbCo ...
- EF4.1之贪婪加载和延迟加载
默认情况下,EF4.1是只查询到涉及到的数据对象,但是EF4.1支持两种方法进行控制其加载: 1.贪婪加载 2.延迟加载 使用的表还是上次使用的Order 和 OrderDetails两张表来举例说明 ...
- EntityFramework(EF)贪婪加载和延迟加载的选择和使用
贪婪加载:顾名思议就是把所有要加载的东西一 次性读取 1 using (var context = new MyDbContext()) 2 { 3 var orders = from o in co ...
- 浅谈Entity Framework中的数据加载方式
如果你还没有接触过或者根本不了解什么是Entity Framework,那么请看这里http://www.entityframeworktutorial.net/EntityFramework-Arc ...
随机推荐
- 编译和安装在Windows上橡胶树 (Compiling and Installing Yate on Windows)
编译和安装在Windows上橡胶树 有两种方法来安装橡胶树下窗口: 下载并安装橡胶树 下载后页面设置. 另一个选择是下载橡胶树从SVN并编译它. 内容 ( 隐藏] 1 安装使用设置橡胶树 2 ...
- MPTCP 源码分析(一) MPTCP的三次握手
简述: MPTCP依然按照正常的TCP进行三次握手,只是在握手过程中增加了MPTCP特有的信息. 建立过程 三次握手过程如下图所示: 左边客户端发送的第一个SYN包携带有客户端 ...
- VB断点调试
最近都在敲机房收费系统,这个系统是我们第一次自己在没有源代码的情况下进行的系统. 写程序的时候逻辑非常重要,可是我们还要清楚非常多时候你以为的并非你以为的! 就像在敲机房的时候,我们明明理清了逻辑.并 ...
- 如何在Django1.6结合Python3.3版本中使用MySql
用起了Python3.4跟Django1.6,数据库依然是互联网企业常见的MySql. 悲催的是在Python2.7时代连接MySql的MySQLdb还不支持Python3.4,还好,苦苦追问G哥终于 ...
- Navicat Premium 连接 Oracle 数据库
Navicat Premium 是一个可多重连接的数据库管理工具,它可让你以单一程序同時连接到 MySQL.SQLite.Oracle 及 PostgreSQL 数据库,让管理不同类型的数据库更加方便 ...
- pomodoro源码
有网友问我要pomodoro源码.事实上这个程序非常easy,仅仅是定时器,定时弹出置顶窗体.用c++builder6.0写.放一个TPopupMenu 右键菜单,一个TTrayIcon 一个托盘图标 ...
- 测试代码覆盖率工具学习(Android Emma)
博客分类: 工具分享 eclipseeclemmaemmatestng 关于eclemma的历史和怎么安装,请参考http://www.ibm.com/developerworks/cn/ ...
- LoadRunner变量到参数的互换
作者QQ:764714258,转载请说明出处,阅读此文需要良好的C基础 LoadRunner中,web性能测试使用的脚步是C语言编写的.C语言中有变量的概念,LoadRunner工具中带有参数这个概念 ...
- git个人使用总结(界面版)
最近开始使用GIT来管理测试文档,从0到1开始使用git 1.首先,使用网页登录GIT后,创建项目 2.创建项目后,需要配置一下访问者权限 3.然后在网页版GIT复制地址,git clone到 本地 ...
- IOS开发准备 资料集锦
1 http://blog.csdn.net/column/details/xfzl-kykhd.html 2