实体框架-使用依赖对象的长链进行高效的热切加载
本文关键字:高效 加载 依赖 实体 对象 框架 | 更新日期: 2024-07-22 23:43:44
我遇到了一个问题,我想许多专业开发人员都会遇到这个问题。我的工作场所采用了实体框架。我们使用它,并且喜欢它。然而,我们似乎遇到了一个非常令人沮丧的限制。
假设你有一个像这样的对象链
A->B->C->D
我们是专业人员,所以这些对象有很多数据,并且在它们各自的数据库表中有很多数据。EF加载对象B之后的任何内容似乎都要花很长时间。它生成的SQL查询效率很低,而且不好。这个电话可能有点像
context.objects.include("bObjectName.cObjectName.dObjectName").FirstOrDefault(x => x.PK == somePK);
我们已经通过使用.Load()命令显式加载超过第二级的对象来解决这个问题。这适用于单个对象。然而,当我们谈论对象的集合时,我们开始遇到.Load().的问题
首先,似乎没有一种方法可以在没有虚拟关键字的情况下保持对集合中对象的代理跟踪。这是有意义的,因为它需要覆盖get和set函数。但是,这会启用延迟加载,并且在启用延迟加载时.Load()不会映射实体。我自己也觉得这有点奇怪。如果删除虚拟关键字,.Load()会自动将加载的对象链接到上下文中的相关对象。
因此,这是我问题的症结所在。我想要代理跟踪,但也希望.Load()为我映射导航属性。如果EF能够生成好的查询,这些都不会成为问题。我理解为什么不能,它必须是一个一刀切的节目。
因此,为了加载第三层对象,我可以在服务层中创建一个loader函数,该函数获取第二层对象的所有主键,然后对它们调用.load()。有人能解决这个问题吗?看起来EF7或Core 1.0通过以下方式解决了这个问题:
- 完全删除懒惰加载,我们也可以关闭它,但它会破坏许多旧代码
- 添加一个新的"TheInInclude"功能,据说可以大大提高链接的效率
如果关闭懒惰加载是答案,那没关系,我只想在浪费大量时间重新开发一个巨大的网络应用程序之前用尽所有选项。有人有什么想法吗?我愿意尝试任何事情。我们正在使用EF6。
编辑:答案似乎是在上下文级别关闭延迟加载,或者升级到EF7。如果其他人能够找到一个解决方案,通过强制加载EF6的单个对象来进行代理跟踪,我会改变这一点。
您对chained.Include()语句的看法是绝对正确的,性能文档警告每个语句不要链接超过3个。Include)添加了一个外部联接或并集。我不知道TheInInclude,但它听起来像是游戏规则的改变者!
如果您保留虚拟导航属性,但关闭DbContext 上的Lazy Loading
context.ObjectContext().ContextOptions.LazyLoadingEnabled = false;
然后(只要启用了更改跟踪),您可以执行以下操作:
var a = context.aObjectNames.First(x=> x.id == whatever);
context.bObjectNames.Where(x=> x.aId == a.Id).Load()
这应该填充a.bObjects