想要实体框架6.1急切加载只加载第一级

时间:2014-06-04 01:57:18

标签: entity-framework entity-framework-6.1

我不确定我是接近错误的方式还是默认行为,但它没有像我期待的那样工作......

以下是两个示例类......

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public Department Department { get; set; }
}

第二个是部门

public class Department
{
    public string Name { get; set; }

    public List<Person> People { get; set; }
}

上下文配置

public MyDbContext() : base("DefaultConnection") 
{
    this.Configuration.ProxyCreationEnabled = false;
    this.Configuration.LazyLoadingEnabled = false; 
}

public DbSet<Person> People { get; set; }
public DbSet<Department> Departments { get; set; }

我正在尝试加载名字来自史密斯&#39;

的人
var foundPeople 
        = context
              .people
              .Where(p => p.LastName == "Smith");

上面的查询加载foundPeople只有FirstName和LastName没有Department对象。这是一个正确的行为,因为我的LazyLoading已关闭。这也是预期的。

现在在另一个带有Eager加载部门的查询中,

var foundPeople 
        = context
              .people
              .Where(p => p.LastName == "Smith")
              .Include(p => p.Department);

上面的查询加载了带有FirstName,LastName,Department with Department-&gt; Name以及Deparment-&gt; People的人们(该部门的所有人,我不想要,我只想加载Included属性的第一级

我不知道这是预期的行为还是我犯了一些错误。

有没有办法只加载第一级包含的属性,而不是完成图表或所有级别的包含属性。

3 个答案:

答案 0 :(得分:3)

使用Include()实现预先加载只有在对象上启用延迟加载时才有效 - 也就是说,您的导航属性必须声明为virtual,以便EF代理可以使用延迟加载行为覆盖它们。 否则,他们会急切加载,Include()将无效。

Person.DepartmentDepartment.People声明为虚拟属性后,您的代码应按预期工作。

非常抱歉,我的原始答案完全不正确。我没有仔细阅读你的问题,事实上对于急切的行为是不正确的。不确定我在想什么(或者是谁投票了?)。真正的答案在下面:


使用您发布的示例模型(进行必要的修改:实体的键并从上下文构造函数中移除&#34; this&#34;)我无法完全重现你的问题。但是,我不认为它正在按照你的想法去做。

当您急切加载部门(或使用context.Entry(...).Reference(...).Load()明确加载)时,请更仔细地检查您的结果:Department.People集合中有元素,但 all 人员,仅查询本身加载的人员。我想你会在最后一个片段中找到!foundPeople.SelectMany(p => p.Department.People).Any(p => p.LastName != "Smith") == true。也就是说,他们都不是史密斯&#34;。

我认为没有办法解决这个问题。实体框架未明确或急切地加载人员集合(您可以Include(p => p.Department.People))。由于模型中的循环关系,它只是将加载到其相关对象的那些链接起来。此外,如果在加载其他人的同一上下文中存在多个查询,则它们也将链接到对象图中。

(旁白:在这种简化的情况下,代理创建和延迟加载配置是多余的 - 由于既没有懒惰或代理能(虚拟)属性,也没有在实体上启用 - 我做的一件事第一次就做对了。)

答案 1 :(得分:2)

通过设计,DbContext做了所谓的“关系修复”。由于您的模型具有关于您的实体之间关系的信息,因此无论何时附加或修改实体,EF都会尝试“修复”实体之间的关系。

例如,如果在上下文中加载具有FK的实体,该实体指示它是已附加到上下文的另一个实体的子项,则它将被添加到现有实体的子集合中。如果您制作任何字符(更改FK,删除实体等),关系将自动修复。这就是另一个答案所解释的:即使您使用不同的查询分别加载相关实体,它们也会附加到它们所属的子集合中。

无法禁用此功能。请参阅与此相关的其他问题:

如何摆脱相关实体

我不知道您需要做什么,但使用当前版本的EF,您必须detach the entity from the context并手动删除相关实体。

另一种选择是使用AutoMapper或ValueInjecter进行映射,以消除关系修复。

答案 2 :(得分:-2)

您可以尝试使用LINQ查询,以便只选择所需的字段。我希望有所帮助。