实体框架延迟加载不正确的实体

时间:2016-07-05 12:30:58

标签: c# entity-framework lazy-loading

考虑以下(非常简化的)实体:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Answer
{
    public int Id { get;set; }
    public virtual User User { get; set; }
    public string Text { get;set }
}

public class TeamMember
{
    public int Id { get;set; }
    public virtual User User { get; set; }  
    public string Role { get; set; }
}

在我的映射器中,我可以设置用户正常,但只要执行以下代码(在数据库中保留任何更改之前)

if (teamMembers.Select(x => x.User).Contains(currentUser))

其中teamMembers是TeamMembers列表,currentUser是从Db加载的User实体,则Answer的User属性设置为数据库中的先前值。 我的理解是,因为我还没有从数据库中加载之前没有访问过它的用户属性,这就是发生的事情(它已被延迟加载?)。

我可以通过在将其设置为映射器之前阅读用户来修复它,但我无法理解的是为什么当我访问TeamMember的User属性时,Answer的User属性被加载并设置?这是预期的行为,因为两个实体都与同一个用户相关联(即在数据库中它们具有与外键相同的User_Id),并且当为TeamMembers加载它时,EF会尝试变得聪明并填充引用它的其他实体并避开'已经装好了吗?

1 个答案:

答案 0 :(得分:0)

实体不会被引用它们的元素存储/缓存,而是与它们各自的集合一起存储。

通过teamMembers引用加载该用户后,它已加载...句点。当你从另一个元素/对象引用它时,当它已经在内存中有该对象时再去加载它将是愚蠢的。

这完全是设计的,它是有道理的...例如,如果你想同时保存所有这些对象,它首先会创建用户,获取它的身份/密钥,然后保存使用生成的密钥引用它的其他对象。

参考:https://msdn.microsoft.com/en-us/data/hh949853.aspx#3

  

" ... ObjectContext将检查具有相同密钥的实体是否具有   已经加载到它的ObjectStateManager中。如果有实体的话   相同的密钥已经存在EF将其包含在结果中   查询。虽然EF仍会针对数据库发出查询,   此行为可以绕过实现实体的大部分成本   多次。"