考虑以下(非常简化的)实体:
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会尝试变得聪明并填充引用它的其他实体并避开'已经装好了吗?
答案 0 :(得分:0)
实体不会被引用它们的元素存储/缓存,而是与它们各自的集合一起存储。
通过teamMembers引用加载该用户后,它已加载...句点。当你从另一个元素/对象引用它时,当它已经在内存中有该对象时再去加载它将是愚蠢的。
这完全是设计的,它是有道理的...例如,如果你想同时保存所有这些对象,它首先会创建用户,获取它的身份/密钥,然后保存使用生成的密钥引用它的其他对象。
参考:https://msdn.microsoft.com/en-us/data/hh949853.aspx#3
" ... ObjectContext将检查具有相同密钥的实体是否具有 已经加载到它的ObjectStateManager中。如果有实体的话 相同的密钥已经存在EF将其包含在结果中 查询。虽然EF仍会针对数据库发出查询, 此行为可以绕过实现实体的大部分成本 多次。"