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

本文关键字:实体 不正确 延迟加载 框架 | 更新日期: 2023-09-27 17:54:47

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

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; }
}

在我的映射器中,我可以设置User fine,但是一旦执行以下代码(在数据库中持久化任何更改之前)

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

,其中teamMembers是teamMembers的列表,currentUser是从数据库加载的User实体,那么Answer的User属性被设置为数据库中的前一个值。我的理解是,因为我还没有访问答案的用户属性之前,它还没有从数据库中加载,这就是发生的事情(它是懒惰加载?)。

我可以通过阅读用户来修复它,甚至在映射器中设置它,但我无法理解的是,为什么当我访问TeamMember的User属性时,会加载和设置Answer的User属性?这是预期的行为,因为两个实体都与相同的用户相关联(即在数据库中,他们有相同的User_Id作为一个外键),当加载它的TeamMembers, EF试图是聪明的,并填充其他实体引用它,还没有加载?

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

实体不是由引用它们的元素存储/缓存的,而是存储在它们各自的集合中。

一旦你通过teamMembers引用加载了User,它就被加载了…时期。当你从另一个元素/对象中引用它时,当它已经在内存中拥有那个对象时,再去加载它是愚蠢的。

这都是由设计和它是有意义的…例如,如果您希望同时保存所有这些对象,它将首先创建用户,获取其标识/密钥,然后保存使用生成的密钥引用该用户的其他对象。

裁判:https://msdn.microsoft.com/en-us/data/hh949853.aspx # 3

"……ObjectContext将检查具有相同键的实体是否具有已经加载到它的ObjectStateManager中。如果一个实体具有相同的键已经存在,EF将把它包含在查询尽管EF仍然会对数据库发出查询,这种行为可以绕过实体实现的大部分成本很多次了。"