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

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 次服务器的查询,但是仍然是可以接受的,特别是考虑到贪婪加载的效率问题。

转载于:https://www.cnblogs.com/tianboblog/p/3229228.html

Entity Framework 4.1 : 贪婪加载和延迟加载相关推荐

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

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

  2. mysql eager mode_MySQL Connector Net 6.6.5 Entity Framework 显式预加载 Eager Load Bug

    在将原有系统从MSSQL迁移到MySQL时,遇到莫名其妙的问题,经过排除大法反复试验,锁定问题出自MySQL官方出品的Entity组件.又经过网上搜索,发现类似问题存在由来已久 http://bugs ...

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

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

  4. Entity Framework Core导航属性加载问题

    前言 今天下午在开发的时候发现EF Core实体模型中的导航属性为 null,经排查既不是没有加 virtual 关键字,也不是外键关系映射错误. 解决方法 通过查询官网文档,发现,原因在于EF Co ...

  5. FreeSql (二十六)贪婪加载 Include、IncludeMany、Dto、ToList

    贪婪加载顾名思议就是把所有要加载的东西一次性读取. 本节内容为了配合[延时加载]而诞生,贪婪加载和他本该在一起介绍,开发项目的过程中应该双管齐下,才能写出高质量的程序. Dto 映射查询 Select ...

  6. 【EF学习笔记07】----------加载关联表的数据 贪婪加载

    [EF学习笔记07]----------加载关联表的数据 贪婪加载 讲解之前,先来看一下我们的数据库结构:班级表 学生表 贪婪加载 //贪婪加载 using (var db = new Entitie ...

  7. hibernate的懒加载(延迟加载)问题

    hibernate的懒加载(延迟加载)问题 我们在开发的时候经常会遇到延迟加载的问题,在实体映射中多对一和多对多中,多的一方的属性默认是lazy="true"(即,默认是延迟加载) ...

  8. Java 单例模式:懒加载(延迟加载)和即时加载

    Java 单例模式:懒加载(延迟加载)和即时加载 引言 在开发中,如果某个实例的创建需要消耗很多系统资源,那么我们通常会使用惰性加载机制(或懒加载.延时加载),也就是说只有当使用到这个实例的时候才会创 ...

  9. Entity Framework 4 in Action读书笔记——第四章:使用LINQ to Entities查询:预先加载和延迟加载...

    4.9 加载(Fetching) 预先加载指在一个查询中加载所有的实体和关联的数据.延迟加载指使用时再加载关联的实体.预先加载是检索数据最高效的方法.尽管它从数据库中检索所有的数据,但是只访问一次数据 ...

最新文章

  1. Memcache内存分配策略
  2. 深度报告:中国将主宰5G时代?华为中兴的最大机会来了
  3. qml demo分析(threading-线程任务)
  4. 06. 为知笔记 -- 我的修改
  5. [导入]sqlserver2005 数据挖掘控件研究
  6. 对话实录|华为云.通信云激活无限商业潜力
  7. Atom飞行手册翻译: 2.1 Atom中的包
  8. java程序员需要掌握的知识,看完直接跪服
  9. Android编程 获取网络连接状态 及调用网络配置界面
  10. 使用Windows 7 管理Windows 2008 R2
  11. JAVA B2B2C多用户商城系统源码 网上商城源码
  12. MSM8937的sbl1和CDT
  13. Linux内核分析学习路线总结(内核人员必看)
  14. php解析识别二维码内容
  15. Redis高频面试题完整版
  16. 苹果摊上事了,iPhone 13新机大翻车,坑害无数人
  17. 计算机主板i3 i5区别,装机那些事儿之挑选适合自己的CPU;i3/i5/i7的区别
  18. Python爬取当当网APP数据
  19. 利用shell脚本将json文件导入es
  20. Linux搭建部署Ldap服务器,亲测可用

热门文章

  1. mysql+distinct+max_MySQL中distinct与group by之间的性能进行比较
  2. debian命令乱码_Debian 9.5 解决中文显示乱码
  3. java 8.0 sinffer_jpcap 配置方法,问题解决,模拟sniffer程序。(附JAVA程序,jar,dll包等环境)...
  4. c语言成绩管理系统开题报告,学生信息管理系统,开题报告(共篇).doc
  5. java struts 框架_java中struts 框架的实现
  6. python3异步协程爬虫,simpyder
  7. IOS ActivityIndicator 活动指示器使用
  8. mysql 删除表记录的 存储过程命令_用SQL语句删除一个数据库的所有表和所有存储过程...
  9. python基础(15)之 继承
  10. vue.js上传头像插件_一个基于vue2.0的头像上传组件