【发布时间】:2018-10-10 17:59:33
【问题描述】:
在调试一些性能问题时,我发现 Entity 框架正在通过延迟加载加载大量记录(900 个额外的查询调用并不快!)但我确信我有正确的包含。我已经设法把它归结为一个很小的测试用例来证明我遇到的困惑,实际用例更复杂,所以我没有很大的空间来重新设计我的签名我正在做,但希望这是我遇到的问题的一个明显例子。
文档有许多相关的 MetaInfo 行。我想获取按具有特定值的 MetaInfo 行分组的所有文档,但我希望包含所有 MetaInfo 行,因此我不必为所有 Documents MetaInfo 发起新请求。
所以我有以下查询。
ctx.Configuration.LazyLoadingEnabled = false;
var DocsByCreator = ctx.Documents
.Include(d => d.MetaInfo) // Load all the metaInfo for each object
.SelectMany(d => d.MetaInfo.Where(m => m.Name == "Author") // For each Author
.Select(m => new { Doc = d, Creator = m })) // Create an object with the Author and the Document they authored.
.ToList(); // Actualize the collection
我希望这包含所有 Document / Author 对,并填充所有 Document MetatInfo 属性。
事实并非如此,我得到了 Document 对象,而 Authors 就好了,但是 Documents MetaInfo 属性只有 Name == "Author" 的 MetaInfo 对象
如果我将 where 子句从 select many 中移出,它会做同样的事情,除非我在实现之后将它移到(虽然这里可能没什么大不了的,但它在实际应用程序中,因为这意味着我们获得比我们想要处理的更多的数据。)
在尝试了很多不同的方法之后,我认为问题在于当您执行 select(...new...) 以及 where 和 include 时。在实现之后执行 select 或 Where 子句会使数据按我预期的方式显示。
我认为这是 Document 的 MetaInfo 属性被过滤的问题,因此我将其重写如下以测试理论,并惊讶地发现这也给出了相同的(我认为是错误的)结果。
ctx.Configuration.LazyLoadingEnabled = false;
var DocsByCreator = ctx.Meta
.Where(m => m.Name == "Author")
.Include(m => m.Document.MetaInfo) // Load all the metaInfo for Document
.Select(m => new { Doc = m.Document, Creator = m })
.ToList(); // Actualize the collection
由于我们没有将 where 放在 Document.MetaInfo 属性上,我希望这可以绕过问题,但奇怪的是,文档似乎仍然只有“作者”MetaInfo 对象。
我创建了一个简单的测试项目并将其上传到 github,其中包含一堆测试用例,据我所知,它们应该全部通过,只有那些过早实现通过的错误.
https://github.com/Robert-Laverick/EFIncludeIssue
有人有任何理论吗?我是否以某种我想念的方式滥用 EF / SQL?有什么我可以做不同的事情来获得相同的结果吗?这是 EF 中的一个错误,它只是被默认情况下打开的 LazyLoad 隐藏在视图之外,并且它有点奇怪的组类型操作?
【问题讨论】:
标签: c# .net entity-framework entity-framework-6