我正在研究基于网络的新报告系统的数据层基础,并且花了很多时间评估过去几天的ORM。也就是说,我之前从未处理过“延迟加载”,并且对于为什么它是实体框架中LINQ查询的默认设置感到困惑。它似乎会创建大量的网络流量,并且不必要地使用其他查询对数据库执行任务,否则可以通过连接来解析这些查询。
有人可以描述延迟加载会有益的场景吗?
有些元:
新系统将在生产环境中针对数百个表和数TB数据的数据库进行工作,系统中每天24小时有超过3,000个并发用户。他们将连续检索大型数据集。 ORM是否可能不是满足我们需求的正确解决方案,特别是因为该应用程序将基于网络?
答案 0 :(得分:5)
当我们谈论延迟加载时,我们讨论的是导航属性(我们如何遵循外键)。延迟加载将为我们做的是在我们尝试访问该实体时从远程表填充实体。例如,如果我们有这样的模型
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 performance tuning cheat sheet,如果您决定在大型查询中使用EF,请阅读DetectChanges和AsNoTracking。
答案 1 :(得分:2)
一个简单的案例是N条记录的结果集,您不想立即将其带到客户端。好处是你可以懒得只加载客户需求所需的东西,例如排序,过滤等......一个例子是分页视图,其中一个人可以翻阅记录并相应地对它们进行排序,从而客户端在给定时间只需要N金额。
执行LINQ查询时,它会将其转换为服务器端的SQL命令,以仅提供给定上下文中所需的内容。它归结为将工作卸载到数据库并最小化您需要发送回客户端的内容。
有些人认为基于ORM的延迟加载是错误的,但是开始转向语义相当快,应该更多地关注设计方法与正确和错误
答案 2 :(得分:2)
大多数ORM会为您提供选项,当您构建对象选择时,说“不要懒惰,继续加入”,所以如果您从效率角度担心,请不要不会。你可以(通常)使它工作。
我知道延迟加载有两个特殊情况:
链接命令 如果要创建基本选择,但希望通过基于用户输入的排序和过滤功能运行它,该怎么办?您可以简单地传递ORM对象,并将排序和过滤功能附加到其中。它不是每次都进行评估,而是仅评估实际使用的时间。
避免巨大,深层,高度关系的查询 如果您只需要某些相关字段的ID,该怎么办?如果它延迟加载,您不必担心它会加入一大堆您不需要的数据和表,这可能会减慢查询速度并过度使用带宽。当然,如果你想要其他所有东西,那么你需要明确,否则你可能遇到一个问题,它懒洋洋地为每个细节记录运行一个查询。就像我在开始时提到的那样,任何值得使用的ORM都可以轻松克服。