10

我正在研究新的基于 Web 的报告系统的数据层基础,并且在过去几天中花费了大量时间评估 ORM。也就是说,我以前从未处理过“延迟加载”,并且对为什么它是 Entity Framework 中 LINQ 查询的默认设置感到困惑。似乎它会产生大量的网络流量,并且不必要地使用额外的查询来处理数据库,否则这些查询可以通过连接来解决。

有人能描述一个延迟加载会带来好处的场景吗?

一些元数据:

新系统将在每天 24 小时在系统上拥有超过 3,000 名并发用户的生产环境中处理具有数百个表和数 TB 数据的数据库。他们将不断地检索大型数据集。ORM 是否可能不是满足我们需求的正确解决方案,尤其是因为该应用程序将是基于 Web 的?

4

3 回答 3

7

当我们谈论延迟加载时,我们正在谈论导航属性(我们如何遵循外键)。延迟加载将为我们做的是在我们尝试访问该实体时从远程表中填充该实体。例如,如果我们有这样的模型

public class TestEntity
{
    public int Id{get;set;}
    public AnotherEntity RemoteEntity{get;set;}
}

并调用以下

var something = WhateverContext.TestEntities.First().RemoteEntity;

我们将获得 2 个数据库调用,一个WhateverContext.TestEntities.First()用于加载远程实体,一个用于加载远程实体。

我是一个网络人,(更具体地说是一个 MVC 人),对于网络东西,我认为没有充分的理由想要这样做,如果我们需要,一个数据库调用总是比两个快同一组数据。

我认为延迟加载实际上值得考虑的情况是,当您不知道何时进行第一次查询时,您是否需要第二个实体。在我看来,这与我们有一个实时执行操作的用户的 Windows 应用程序更相关(而不是用户一次请求整个页面的无状态 MVC)。例如,当我们有一个带有详细信息链接的数据列表时,我认为延迟加载会大放异彩,然后我们不会加载详细信息,直到用户决定他们想要查看它们。

我不认为这延伸到分页、排序和过滤,IMO 应该有一个专门设计的数据库查询,每页显示的数据,它返回的正是显示该页面所需的数据集。

就您的性能问题而言,我认为 EF(或其他 ORM)可能在这里可以满足您的需求,但是由于 EF 跟踪实体的方式,您要小心如何检索大型数据集。查看我的EF 性能调整备忘单,如果您决定将 EF 用于大型查询,请阅读DetectChangesAsNoTracking 。

于 2012-12-22T04:20:56.197 回答
2

一个简单的案例是一个包含 N 条记录的结果集,您不想一次将其提供给客户端。好处是您可以仅延迟加载客户需求所需的内容,例如排序,过滤等......一个示例是分页视图,其中可以分页浏览记录并相应地对它们进行排序,因此客户端在给定时间只需要 N 量。

当您执行 LINQ 查询时,它会将其转换为服务器端的 SQL 命令,以仅提供给定上下文中所需的内容。它归结为将工作卸载到数据库并最小化您需要发送回客户端的内容。

有些人会争辩说,基于 ORM 的延迟加载是错误的,但是它开始相当快地转向语义,并且应该更多地关注设计方法而不是

于 2012-12-22T03:26:47.647 回答
2

大多数 ORM 会在您构建对象选择时为您提供选项,说“不要偷懒,继续加入”,所以如果您从效率的角度担心它,请不要. 你可以让它工作(通常)。

我知道有两种特殊情况可以帮助延迟加载:

  1. 链接命令 如果您想创建一个基本选择,但您想通过基于用户输入的排序和过滤功能运行它,该怎么办。您可以简单地传入 ORM 对象,并将排序和过滤功能附加到它。它不是每次都评估它,而是仅在实际使用时评估。

  2. 避免大型、深度、高度相关的查询 如果您只需要一些相关字段的 ID,该怎么办?如果它延迟加载,您不必担心它会加入一大堆您不需要的数据和表,这可能会减慢查询速度并过度使用带宽。当然,如果您确实想要其他所有内容,那么您需要明确,否则您可能会遇到一个问题,即它懒惰地为每个详细记录运行查询。就像我在一开始提到的那样,这在任何值得使用的 ORM 中都很容易克服。

于 2012-12-22T03:30:45.600 回答