Gau*_*ver 5 c# linq asp.net-mvc performance entity-framework
我有一个问题,我认为很多专业开发人员会遇到这个问题.我的工作场所采用了实体框架.我们使用它,并喜欢它.但是,我们似乎遇到了一个非常令人沮丧的限制.
我们假设您有一个对象链
A - > B - > C - > D.
我们是专业人士,因此这些对象拥有大量数据,并且在各自的数据库表中有很多数据.看起来EF在加载任何超过对象B的东西时都会遇到很糟糕的时间.它生成的SQL查询效率非常低且不好.电话会是这样的
context.objects.include("bObjectName.cObjectName.dObjectName").FirstOrDefault(x => x.PK == somePK);
Run Code Online (Sandbox Code Playgroud)
我们通过使用.Load()命令显式加载超过第二级的对象来解决这个问题.这适用于单个对象.但是,当我们谈论一组对象时,我们开始遇到.Load()的问题.
首先,似乎没有办法在没有virtual关键字的情况下保持集合中对象的代理跟踪.这是有道理的,因为它需要覆盖get和set函数.但是,这会启用延迟加载,并且.Load()在启用延迟加载时不会映射实体.我觉得这有些奇怪.如果删除虚拟关键字,.Load()会自动将加载的对象链接到上下文中的相关对象.
所以这是我的问题的关键.我想要代理跟踪,但也希望.Load()为我映射导航属性.如果EF可以生成良好的查询,这些都不会成为问题.我理解为什么它不能,它必须是一个适合所有类型的东西.
因此,要加载第三层对象,我可以在服务层中创建一个加载器函数,它接受第二层对象的所有主键,然后在它们上调用.Load().有人有解决方案吗?好像EF7或Core 1.0通过以下方式解决了这个问题:
如果关闭延迟加载是答案,那很好,我只想浪费所有选项,然后浪费大量时间重新开发一个巨大的webapps值得服务电话.有没有人有任何想法?我愿意付出一些代价.我们正在使用EF6.
编辑:似乎答案是在上下文级别关闭延迟加载,或升级到EF7.如果其他人设法找到一个解决方案,你可以通过强制急切加载EF6的单个对象进行代理跟踪,我会改变这个.
您对链接的 .Include() 语句的看法绝对正确,性能文档警告不要链接超过 3 个语句,因为每个 .Include() 添加一个外部联接或联合。我不知道 ThenInclude,但它听起来像是一个游戏规则改变者!
如果保留虚拟导航属性但关闭 DbContext 上的延迟加载
context.ObjectContext().ContextOptions.LazyLoadingEnabled = false;
Run Code Online (Sandbox Code Playgroud)
然后(只要启用了更改跟踪)您可以执行以下操作:
var a = context.aObjectNames.First(x=> x.id == whatever);
context.bObjectNames.Where(x=> x.aId == a.Id).Load()
Run Code Online (Sandbox Code Playgroud)
这应该填充 a.bObjects