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

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. 项目笔记:导出Excel功能设置导出数据样式

    /** * 导出-新导出 * * @return * @throws IOException */ @OperateLogAnn(type = OperateEnum.EXPORT, hibInter ...

  2. zabbix通过percona插件监控mysql

    percona zabbix mysql-plugin是percona发布的一个使用zabbix监控mysql数据库的工具,这款工具比zabbix自带的监控模板要强大的多,毕竟percona是Mysq ...

  3. PS 如何制作环绕文字效果

    最终效果 地球素材 1.打开素材,使用椭圆选区工具按住shift绘制正圆选区 2.转到路径面板,将选区变为工作路径 3.选择文字工具,在路径上输入文字 4.ctrl+T,按住ctrl+alt,鼠标拖动 ...

  4. Vue笔记五

    十二.过滤器(filter) 示例代码: <template> <div id="app"> {{ msg | capitalize }} </div ...

  5. Laravel之控制器

    一.简介 将所有的请求处理逻辑都放在单个routes.php 中肯定是不合理的,你也许还希望使用控制器类组织管理这些行为.控制器可以将相关的 HTTP 请求封装到一个类中进行处理.通常控制器存放在ap ...

  6. 改变datagrid中指定单元格的值

    //自己设置编辑时显示的内容 $('#purchasegroupname'+index).html(name); //单元格真实内容 $('#material_datagrid').datagrid( ...

  7. 单机Redis实现分布式互斥锁

    代码地址如下:http://www.demodashi.com/demo/12520.html 0.准备工作 0-1 运行环境 jdk1.8 gradle 一个能支持以上两者的代码编辑器,作者使用的是 ...

  8. 监听EditText字数

    editContent.addTextChangedListener(new TextWatcher() { private CharSequence temp;private int editSta ...

  9. POJ1328 Radar Installation 【贪心&#183;区间选点】

    Radar Installation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 54593   Accepted: 12 ...

  10. 安装java运行环境

    1.查看java安装版本 执行命令java -version查看已安装java运行环境信息. 2.下载JDK 到sun官网下载需要的jdk版本,地址为:http://www.oracle.com/te ...