这篇文章将讨论查询结果的加载控制。

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 : 贪婪加载和延迟加载的更多相关文章

  1. EF之贪婪加载和延迟加载

    这篇文章将讨论查询结果的控制 在使用EF(Entity Framework)的过程中,很多时候我们会进行查询的操作,因此知道哪些数据会被加载到内存当中就至关重要.在多多的情况下,你可能并并不需要加载全 ...

  2. 【EfF】 贪婪加载和延迟加载 (virtual去掉关闭延迟加载)

    EntityFramework(EF)贪婪加载和延迟加载的选择和使用 贪婪加载:顾名思议就是把所有要加载的东西一 次性读取 1 using (var context = new MyDbContext ...

  3. EF中的贪婪加载和延迟加载(懒加载)

    在上一章中,我们使用了Linq对Entity Framework进行了一个查询,但是通过学习我们却发现了懒加载给我来的性能上的开销是很到的,尤其是在循环中,如果数据量不是很多的情况下还可以接受,如果数 ...

  4. EntityFramework 贪婪加载与延迟加载以及资源回收

    EntityFramework的资源回收 1) Using 内包含Entity的上下文关系,对俩表做Add操作,最好可以直接写一个 entity.SaveChanges(); 完成两张表的同时add操 ...

  5. 学习EF之贪婪加载和延迟加载(1)

    从暑假开始接触code first以来,一直感觉很好用,主要在于开发过程中以业务为中心可以随时修改数据模型生成数据库,还有一个原因就是查询起来很方便 这里找了一个以前database first的一段 ...

  6. 【转】EntityFramework(EF)贪婪加载和延迟加载的选择和使用

    原谅:http://www.weixq.cn/Article/Detail/906 贪婪加载:顾名思议就是把所有要加载的东西一 次性读取 using (var context = new MyDbCo ...

  7. EF4.1之贪婪加载和延迟加载

    默认情况下,EF4.1是只查询到涉及到的数据对象,但是EF4.1支持两种方法进行控制其加载: 1.贪婪加载 2.延迟加载 使用的表还是上次使用的Order 和 OrderDetails两张表来举例说明 ...

  8. EntityFramework(EF)贪婪加载和延迟加载的选择和使用

    贪婪加载:顾名思议就是把所有要加载的东西一 次性读取 1 using (var context = new MyDbContext()) 2 { 3 var orders = from o in co ...

  9. 浅谈Entity Framework中的数据加载方式

    如果你还没有接触过或者根本不了解什么是Entity Framework,那么请看这里http://www.entityframeworktutorial.net/EntityFramework-Arc ...

随机推荐

  1. 2017.4.7 e.toString() 与 e.getMessage()的区别

    我使用的时候,抛出了空指针异常,本来是想将异常信息显示在errorInfo里,却发现没有拿到错误信息. 原因:我用的是getMessage(). 用e.getMessage() 时,返回的是null. ...

  2. win10 如何配置 java jdk1.8环境变量(2017.8.17 )jdk1.8.0_144

    win10 如何配置 java jdk 环境变量 2017.8.17 本篇还适用于 windows server 2012. windows server 2014+ 一.安装 下载 jdk 64位 ...

  3. 【转载】深入理解JVM性能调优

    性能问题无非就这么几种:CPU.内存.磁盘IO.网络.那我们来逐一介绍以下相关的现象和一些可能出现的问题. 一.CPU过高. 查看CPU最简单的我们使用任务管理器查看,如下图所示,windows下使用 ...

  4. javascript - 封装ajax

    封装,使用有示例. // 封装示例: function ajax(url, method, params, done) { var xhr = null; method = method.toUppe ...

  5. Nginx:管理HTTP模块的配置项

    参考资料<深入理解Nginx> 一个nginx.conf的例子 http { mytest_num ; server { server_name A; listen ; mytest_nu ...

  6. TCP/IP详解 卷一(第十三章 IGMP:Internet组管理协议)

    本章将介绍用于支持主机和路由器进行多播的Internet组管理协议(IGMP) 它让一个物理网络上的所有系统知道主机当前所在的多播组.多播路由器需要这些信息以便知道多播数据报应该向那些接口转发. 跟I ...

  7. ROS当中添加第三方库

      下文以serial 库为依据讲解第三方库在ROS下面的配置. 参考文献:http://blog.csdn.net/u011853479/article/details/51263590 ros中使 ...

  8. 【转】mongoDB命令行和客户端访问

    一.客户端 mongodb客户端常用的是mongoVUE  下载mongoVUE:网上下载地址,并且是破解版.[若没分,可以单独找我].因为非破解版的只有15天的使用限制.         打开界面如 ...

  9. sqlplus登入和plsql登入的差别

    以下是两种登入方式的截图.用sqlplus登入须要输入主机字: 假设是用本机的SQL*Plus连接本机的数据库.则"主机字符串"能够为空. 假设是从远程连接xp的oracle数据库 ...

  10. 【问题记录】web项目访问时出现404

    请一定检查一下项目的Context root是否是你访问时使用的. Context root设置为/时,可以直接用ip+端口访问. Context root设置为项目名的,访问时请带上项目名. 设置方 ...