实体框架 - 解决延迟加载性能问题的最佳做法
本文关键字:最佳 问题 性能 框架 解决 延迟加载 实体 | 更新日期: 2023-09-27 18:31:17
我已经用实体框架接管了一个项目。代码似乎分层良好,结构良好。问题是,正如我在实体框架中多次看到的那样,他们经常使用延迟加载。在数据库获得一些数据并且SQL查询达到峰值之前,问题才出现。
该解决方案充分利用了保持存储库较小并且仅获取一级数据,并且当我处理一些最大的性能问题时,最常见的问题通常通过向加载嵌套实体并使用一些动态查询的存储库添加特定功能来解决。
即获取客户与订单数据,包括订单,订单行等。
有时我必须合并两个查询,首先获取客户(包含关系),然后获取订单(包含)并通过 linq 将它们映射在一起。
查询比示例复杂得多,延迟加载可能在业务层、控制器或视图中,因此有很多需要跟踪来解决的问题。
但是我觉得代码很大,我很难找到未来的问题。我现在需要的是一种很好的方法来跟踪何时出现延迟加载,并且还能够告诉在特定调用中需要加载哪些对象。
最好的办法是,如果我能跟踪特定的操作调用,并获取执行的sql,执行次数,加载时间等。
该解决方案是使用 MVC 3 和 EF4 构建的,升级到较新的 EF 可以获得任何性能吗?
在以前的工作中,这成为一个问题,因为开发人员会滥用框架并到处创建n+1
问题 - 只有在表格变大时才表现出来。此外,如果您没有将序列化深度指定为 1 停止,延迟加载也会给 json 序列化带来问题 - 即使有时相关对象会在那里,有时它们不会(取决于深度),这也很奇怪。
最后,我们完全关闭了延迟加载,并迫使开发人员进行第二次数据库调用以获取他们想要的子实体。此外,团队被指示在开发时保持Sql Server Profiler
,以确保不会产生任何会降低性能的东西。
这种方法肯定也有缺点,例如对数据库的额外往返,额外的代码行,以及新开发人员对团队普遍缺乏理解,为什么我们要做这样的事情。有些人认为我们可以在查询中使用 Include,但在某些时候,我们的存储库会因为这样做而变得臃肿,简单性/可读性也很重要。最后,性能问题变得不存在,所以在我看来,杀死惰性加载的权衡是值得的。
你问过,这不是对这个问题的直接回答,但也许它会给你一些额外的见解。在你的情况下,我会观察 Profiler 以查看最严重的滥用发生在哪里,然后一次修复一个,直到您的表现再次被接受。您可能会发现您的解决方法是执行类似操作,并完全消除延迟加载。
我很想看到这个问题的其他答案,因为在我看来,这是一个重要的话题。