延迟加载与急切加载


79

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

如果有人向我解释在什么情况下,优先加载比延迟加载更有利,以及在有比延迟加载更友好的资源的情况下我们为什么要使用它,我将不胜感激。


8
想象一下这样一种情况,您的数据库上下文将被处置,并且懒惰加载不再发生。那么积极的加载是有益的。
2015年

2
我已经看到很多项目由于“ N + 1 Select”问题而由于性能问题而失败,这在进行延迟加载时会更快地发生,所以一定要查找一下
David DV

Answers:


79

我认为对这样的关系进行分类很好

何时使用紧急加载

  1. 在一对多关系的“一侧”中,您确定与主要实体一起在所有地方使用。例如文章的用户属性。产品的类别属性。
  2. 通常,当关系不是太多并且渴望加载时,减少在服务器上的进一步查询将是一个好习惯。

何时使用延迟加载

  1. 一对多关系的几乎每个“集合方”。如用户文章或类别的产品
  2. 您完全知道您将不需要即时财产。

注意:就像Transcendent所说的,延迟加载可能存在处理问题。


5
我只是想回答同样的事情。当您知道几乎不需要使用相关数据时,请使用延迟加载。但是,当您知道经常需要某些相关数据时,请使用预先加载。
加桑2015年

我可以同时使用两者吗?例如,如果某个实体几乎与另一个实体相关,那么我可以通过快速加载将其包括在内,而其他相关实体则可以通过延迟加载来添加?
艾哈迈德·阿拉

27

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

何时使用:

  1. 关系不太多时,请使用“渴望加载”。因此,急切加载是减少服务器上进一步查询的一种好习惯。
  2. 当您确定要在所有地方使用主要实体时,请使用“急切加载”。

延迟加载:延迟加载的情况下,相关对象(子对象)在请求之前不会自动与其父对象一起加载。默认情况下,LINQ支持延迟加载。

何时使用:

  1. 使用一对多集合时,请使用延迟加载。
  2. 当您确定不立即使用相关实体时,请使用“延迟加载”。

注意:实体框架支持三种加载相关数据的方式-优先加载,延迟加载和显式加载。


我对渴望和延迟加载感到非常困惑。请问您能不能让我理解!通过Google的引用,我认为这与延迟加载有关。“当您要通过延迟加载来加载数据时,应该使用virtual关键字。延迟加载是这样的过程,在该过程中,第一次访问数据库时会自动从数据库中加载实体或实体集合。2016年1月7日”是您说的关于延迟加载的内容也是一样。
rykamol

@rykamol尝试将其理解为一种设计模式。预先加载- :你可以在这里是指为了更好地理解entityframeworktutorial.net/...,延迟加载- entityframeworktutorial.net/...,显式加载- entityframeworktutorial.net/EntityFramework4.3/...
暗物质

20

延迟加载将产生多个SQL调用,而急切加载可能会通过一个“更繁重”的调用(带有联接/子查询)加载数据。

例如,如果您的Web服务器和sql服务器之间的ping较高,则应该使用Eager加载,而不是使用惰性加载按1比1加载相关项。


我可以同时使用两者吗?例如,如果某个实体几乎与另一个实体相关,那么我可以通过快速加载将其包括在内,而其他相关实体则可以通过延迟加载来添加?
艾哈迈德·阿拉

12

考虑以下情况

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)强制加载该文件。


3
是的,这是延迟加载无济于事的示例。另一件事是,每次需要一些数据时都创建DbContext是不好的方法。如果您有一些IoC容器,则您的DbContext将与请求一起使用(对于Web应用程序)。
米罗斯拉夫·霍尔茨

@MiroslavHolec:很棒,这就是我实际上使用Ninject所做的。您刚才提到的内容确实非常好。
2015年

8

急切加载 当您确定要一次获取多个实体时(例如,必须在同一页面上显示用户和用户详细信息),则应该进行急切加载。急切的加载使数据库命中一次,并加载了相关的实体。

延迟加载 当您只需要在页面上显示用户时,通过单击用户需要显示用户详细信息,则需要进行延迟加载。延迟加载会产生多次点击,以在绑定/迭代相关实体时加载相关实体。


1

延迟加载-在处理分页时非常有用,例如页面加载时会出现包含10个用户的用户列表,并且当用户向下滚动页面时,api调用会带来接下来的10个用户。当您不想在以下位置加载enit数据时非常有用一次,因为这将花费更多时间,并且会带来糟糕的用户体验。

预先加载-在其他人之间没有太多关系并且一次调用数据库即可一次获取全部数据时,就像其他人所建议的那样好


-1

最好尽可能使用预先加载,因为它可以优化应用程序的性能。

前:

Eager loading

var customers= _context.customers.Include(c=> c.membershipType).Tolist();

lazy loading

在模型中,客户必须定义

Public virtual string membershipType {get; set;}

因此,在查询延迟加载时,加载所有参考对象的速度要慢得多,但是渴望加载查询并仅选择相关的对象。


使用Glimpse之类的性能诊断工具,并在具有多个连接的延迟加载和渴望的查询只有一个的情况下检查两者的工作方式。实际上,我已经检查过这些内容,请提及您为什么说错了。
Nuwan Dhanushka,

#FakeCaleb已删除他的评论
Nuwan Dhanushka 18/12/13

一个mod删除了我的评论,因为您无论如何都从响应中误解了我的评论,所以我看不到继续对话的意义
FakeCaleb

您没有提到确切的要点,而是说我的评论完全是误导性的,如果您提到哪些是不正确的要点,我也可以学习。
Nuwan Dhanushka '18

我只是认为由于措辞,您暗示由于性能,渴望加载比延迟加载要好。我可以想到的情况并非如此。
FakeCaleb

-2
// 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();
}

1
尽管此代码段可以解决问题,但提供说明确实有助于提高您的帖子质量。请记住,您将来会为读者回答这个问题,而这些人可能不知道您提出代码建议的原因。
何一非何一非

1
这个答案根本没有解决OP的问题。OP并未询问如何操作Lazy loading,而是询问“何时使用Lazy loading和何时使用Eager Loading
Mischa
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.