2015-07-12 93 views
37

实体框架中的延迟加载是加载和访问相关实体时发生的默认现象。然而,急切的加载被称为强制加载所有这些关系的做法。我遇到了什么情况下急切加载比延迟加载更有利的问题。提出这个问题,因为很明显,延迟加载对资源更友好,即使我们使用方法,我们仍然可以利用延迟加载行为。然而,我想可能延迟加载会增加对实际数据库的请求数量,也许这就是为什么有时开发人员使用Inlcude方法强制加载所有关系。例如,当在MVC 5中使用Visual Studio自动脚手架时,在控制器中自动创建的Index方法总是使用Eager Loading,并且在这种情况下,我总是有一个问题,为什么微软默认使用Eager Loading。延迟加载vs预先加载

如果有人向我解释,在什么情况下,加载比延迟加载更有利,我们为什么要使用它,而对于更加资源友好的Lazy Loading来说,我将不胜感激。

+6

想象一下,您的数据库上下文将被丢弃并且不再发生延迟加载的情况。然后急切的加载是有益的。 – Transcendent

+1

我看到很多项目因为性能问题而失败,这是由于“N + 1选择”问题导致的,当执行延迟加载时会出现更快的性能问题,所以一定要看看这个问题 –

回答

37

我觉得这是很好的分类,这样

关系何时使用预先加载

  1. 在您确定用于每一个地方一个一对多的关系的“一面”与主要实体。像一篇文章的用户属性。产品的类别属性。
  2. 通常当关系不太多时,急切的加载将是减少服务器上进一步查询的良好实践。

当使用延迟加载

  1. 几乎在一个一对多关系的每一个“回收侧”。像用户的文章或类别的产品
  2. 你完全知道你不会立即需要财产。

注:像超然说,有可能是处置问题,延迟加载。

+5

我只是试图回答同样的问题。当您知道您很少需要使用相关数据时,请使用延迟加载。但是当你知道你会经常需要某些相关数据时,请使用急切的加载。 –

8

延迟加载会产生几个SQL调用,而Eager加载可能会用一个“更重的”调用(连接/子查询)加载数据。

例如,如果您的web和sql服务器之间的ping值较高,那么您将使用Eager加载,而不是使用延迟加载逐个加载相关项。

9

考虑以下情况后

public class Person{ 
    public String Name{get; set;} 
    public String Email {get; set;} 
    public virtual Employer employer {get; set;} 
} 

public List<EF.Person> GetPerson(){ 
    using(EF.DbEntities db = new EF.DbEntities()){ 
     return db.Person.ToList(); 
    } 
} 

现在这个方法被调用时,你不能延迟加载Employer实体了。为什么?因为db对象被丢弃。所以你必须做Person.Include(x=> x.employer)来强制加载。

+2

是的,这是懒惰加载不起作用的示例。另一件事是每次你需要一些数据时创建DbContext是不好的方法。如果你是一个IoC容器,你的DbContext将与Request一起生活(如果是Web应用)。 –

+0

@MiroslavHolec:非常棒,这就是我实际使用Ninject所做的。你刚刚提到的确实非常好。 – Transcendent

0
// Using LINQ and just referencing p.Employer will lazy load 
// I am not at a computer but I know I have lazy loaded in one 
// query with a single query call like below. 
List<Person> persons = new List<Person>(); 
using(MyDbContext dbContext = new MyDbContext()) 
{ 
    persons = (
     from p in dbcontext.Persons 
     select new Person{ 
      Name = p.Name, 
      Email = p.Email, 
      Employer = p.Employer 
     }).ToList(); 
} 
+0

尽管此代码片段可能会解决此问题,但[包括解释](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers)确实有助于提高帖子的质量。请记住,您将来会为读者回答问题,而这些人可能不知道您的代码建议的原因。 – Arefly

+0

这个答案根本没有解决OP的问题。 OP不问如何做“懒加载”,他问的是“何时使用'懒加载'和何时加载'' – Mischa

5

预先加载: 预先加载帮助您一次加载所有需要的实体。即相关对象(子对象) 会自动加载其父对象。

何时使用:

  1. 使用预先加载时,关系并不太大。 因此,Eager Loading是减少服务器上进一步查询的良好做法。
  2. 使用Eager载入,当你确定你将使用与主要实体相关的实体。

延迟加载: 在延迟加载的情况下,相关对象(子对象)都不会自动 与它的父对象,直到他们被要求加载。 默认情况下,LINQ支持延迟加载。

何时使用:

  1. 使用延迟加载,当您使用一个一对多的集合。
  2. 如果您确定没有立即使用相关实体,请使用延迟加载。

注:实体框架支持三种方法来加载相关的数据 - 预先加载,延迟加载和明确的装载。