【问题标题】:Lazy Loading vs Eager Loading延迟加载与急切加载
【发布时间】:2015-09-30 16:56:51
【问题描述】:

在什么情况下急切加载比延迟加载更有利?

实体框架中的延迟加载是加载和访问相关实体时发生的默认现象。然而,急切加载是指强制加载所有这些关系的做法。

我问这个,因为很明显延迟加载对资源更友好,即使我们使用ToList()方法,我们仍然可以利用延迟加载行为。

但是,我认为延迟加载可能会增加对实际数据库的请求数量,这可能就是开发人员有时使用Inlcude 方法强制加载所有关系的原因。

例如,当在 MVC 5 中使用 Visual Studio 自动脚手架时,控制器中自动创建的 Index 方法总是使用 Eager Loading,而我一直有一个疑问,为什么微软在这种情况下默认使用 Eager Loading。

如果有人向我解释在什么情况下急切加载会比延迟加载更有益,我将不胜感激,以及为什么我们要使用它,而有一些比延迟加载更资源友好的东西?

【问题讨论】:

  • 想象一下您的数据库上下文将被释放并且延迟加载不再发生的情况。然后急切加载是有益的。
  • 我看到很多项目因为“N + 1 Select”问题导致性能问题而失败,这在延迟加载时会发生得更快,所以一定要查一下

标签: c# entity-framework entity-framework-6


【解决方案1】:

我认为这样分类关系很好

何时使用预加载

  1. 在一对多关系的“一侧”中,您确定在任何地方都使用主实体。比如文章的用户属性。产品的类别属性。
  2. 通常,当关系不是太多时,预先加载将是减少服务器上进一步查询的好习惯。

何时使用延迟加载

  1. 几乎在一对多关系的每个“集合端”。喜欢用户的文章或某个类别的产品
  2. 您完全知道您不会立即需要房产。

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

【讨论】:

  • 我只是想回答同样的问题。当您知道您很少需要使用相关数据时,请使用延迟加载。但是,当您知道您会经常需要某些相关数据时,请使用预加载。
  • 我可以同时使用两者吗?例如,如果实体几乎与另一个实体相关,我可以通过预先加载将其包含在内,而其他相关实体将通过延迟加载?
【解决方案2】:

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

何时使用:

  1. 当关系不是太多时使用急切加载。 因此,Eager Loading 是减少服务器上进一步查询的好习惯。
  2. 当您确定将在任何地方使用与主要实体相关的实体时,请使用 Eager Loading。

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

何时使用:

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

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

【讨论】:

  • 我真的对急切和延迟加载感到困惑。请你让我明白,请!通过参考谷歌,我犯了这个关于延迟加载的事情。 “当你想通过延迟加载加载数据时,你应该使用 virtual 关键字。延迟加载是一个实体或实体集合在第一次访问时自动从数据库加载的过程。2016 年 1 月 7 日”是与您所说的延迟加载相同。
  • @rykamol 尝试将其理解为一种设计模式。你可以参考这里以获得更好的理解:Eager Loading - entityframeworktutorial.net/…,Lazy Loading - entityframeworktutorial.net/…,Explicit Loading - entityframeworktutorial.net/EntityFramework4.3/…
  • @rykamol:如果我要求你获取 Tom 的个人数据,我会提醒你我可能需要他(部分)孩子的个人数据;你愿意一次获取汤姆和他所有孩子的所有这些数据(急切加载)还是你愿意给我汤姆的数据然后向我保证你会去获取他孩子的任何数据如果 我最终要求它(延迟加载)?这两种方法各有千秋,延迟加载可以避免加载未使用的数据,而急切加载可以最大限度地减少访问数据库的次数。
  • @Flater 非常感谢。我不会再忘记了。
【解决方案3】:

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

例如,如果您的 web 和 sql 服务器之间的 ping 值很高,您将使用 Eager 加载而不是使用延迟加载 1-by-1 加载相关项目。

【讨论】:

  • 我可以同时使用两者吗?例如,如果实体几乎与另一个实体相关,我可以通过预先加载将其包含在内,而其他相关实体将通过延迟加载?
【解决方案4】:

考虑以下情况

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=&gt; x.employer) 来强制加载它。

【讨论】:

  • 是的,这是延迟加载没有帮助的例子。另一件事是每次需要一些数据时创建 DbContext 是不好的方法。如果你有一些 IoC 容器,你的 DbContext 将与 Request 一起存在(在 web 应用程序的情况下)。
  • @MiroslavHolec:太棒了,这就是我使用 Ninject 实际所做的。你刚才说的确实非常非常好。
【解决方案5】:

渴望加载 当您确定要一次获取多个实体时,例如您必须在同一页面上显示用户和用户详细信息,那么您应该使用预加载。 急切加载对数据库进行单次点击并加载相关实体。

延迟加载 当您必须仅在页面上显示用户并且通过单击用户需要显示用户详细信息时,您需要使用延迟加载。 延迟加载多次点击,以在您绑定/迭代相关实体时加载相关实体。

【讨论】:

    【解决方案6】:

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

    急切加载 - 就像其他人建议的那样,当关系不多时,只需一次调用数据库即可一次获取全部数据

    【讨论】:

    • 连续滚动或分页!=延迟加载。
    • 是的,先生,这只是为了清楚起见,延迟加载基本上是加载/获取数据,直到需要它为止。
    • 在 Entity Framework 清晰具体的上下文中并不是懒加载。
    【解决方案7】:

    在可能的情况下最好使用预加载,因为它可以优化应用程序的性能。

    前-:

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

    在模型中客户必须定义​​

    Public virtual string membershipType {get; set;}
    

    因此,当查询延迟加载时,加载所有引用对象的速度要慢得多,但急切加载查询并仅选择相关的对象。

    【讨论】:

    • 使用 Glimpse 之类的性能诊断工具检查两者的工作原理,同时延迟加载有多个连接,而急切的查询只有一个。我已经检查了这些,请说明你为什么说错了。
    • #FakeCaleb 已删除他的评论
    • 一个模组删除了我的评论,我没有看到继续这个对话的意义,因为你从你的回复中误解了我的评论
    • 你没有提到确切的点,说我的评论完全是误导,如果你提到哪些点是不正确的,我也可以学习。
    • 我只是认为,由于您的措辞,由于性能,急切加载比延迟加载更好。我可以想到不正确的场景。
    【解决方案8】:
    // 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();
    }
    

    【讨论】:

    • 虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。
    • 这个答案根本没有解决 OP 的问题。 OP 不是在问如何做Lazy loading,而是在问“何时使用Lazy loading 以及何时使用Eager Loading
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多