我无法用实体框架解释的行为

本文关键字:解释 框架 实体 | 更新日期: 2023-09-27 18:12:52

我试图找到关于实体框架中的行为的文档。它可以工作,但在依赖此行为之前,我想确定这是EF的正常行为,而不是一个意想不到的副作用,将在未来的版本中"修复"。情况如下:

我有一个相当深的对象层次结构(我将在这里简化)。该结构是一个多层对象集合(类a包含类B的集合,类B包含类C的集合,类C包含…),深度为7层。

我必须在C的一些属性上过滤元素,我的第一次尝试是加载完整的层次结构,产生一个复杂的LINQ查询(这将是一个维护噩梦),生成的SQL查询远非高效。为了简化这一切,我决定将查询分成两步:首先,我加载经过过滤的类C的集合(及其所有子集合),然后,我为包含经过过滤的C集合项的B的所有实例加载类A和类B。

这里有一个问题:使用该技术,我期望必须在B类中手动重新填充C集合,但实际上,集合已经用集合的元素填充了。我在intellitrace中验证了SQL查询,并且填充C实例所需的数据不包括在第二个查询中,因此唯一合乎逻辑的结论是EF从上下文中的信息中做到了这一点。顺便说一句,在这个上下文中,延迟加载是关闭的。

这种行为在EF中正常吗?如果是这样的话,你能给我一个链接到解释这是如何工作的文档吗?

下面是一个片段来说明这一点:

using(var context = new MyContext())
{
    //Includes and where clauses are greatly simplified for the purpose of the sample
    var filteredC = context.C.Include(x=>x.ListOfD).Include(x=>x.ListOfD.Select(y=>y.ListOfE)).Where(c=>c.Status==Status).ToList();
    int[] bToLoad = filteredC.Select(c=>c.IDofB).Distinct().ToArray();
    var listOfAAndB = context.A.Include(a=>a.ListOfB).Where(x=>x.ListOfB.Any(y=>bToLoad.Contains(y.ID))).ToList();
    //At this step, I expected B.ListOfC to be empty but it's somehow populated
}

谢谢

我无法用实体框架解释的行为

这是DbContext生命周期的标准行为。老实说,我无法将您链接到记录此功能的任何文档,但我可以向您解释它是如何工作的。

EF Context是有状态的,并且跟踪所有已经被获取的实体。它还知道数据库中实体和实体模型之间的关系。

因此,如果您获取与该对象有直接关系的新对象(在您的示例中,C有指向B的外键),则导航属性由Context填充。这是一个特性,而不是bug,因为它试图显式地避免对已经获取的对象延迟加载查询到DB。