【问题标题】:Entity Framework child objects not populating实体框架子对象未填充
【发布时间】:2014-02-06 19:46:17
【问题描述】:

我有一个简单的模型,当我在调试器中运行网站时,实体框架没有正确填充模型。

模型很简单:

public class Team
{
    /// <summary>
    ///     Constructor required for the EntityFramework to create the object.
    /// </summary>
    private Team()
    {            
    }

    public Team(string name, ApplicationUser owner)
    {
        Name = name;
        Owner = owner;
    }

    [Required]
    public int Id { get; private set; }

    [Required]
    public string Name { get; private set; }

    [Required]
    public ApplicationUser Owner { get; private set; }

    [Required]
    public List<TeamMembership> Members { get; set; }
}


public class TeamMembership
{
    /// <summary>
    ///     Constructor for the EntityFramework
    /// </summary>
    private TeamMembership()
    {
    }

    public TeamMembership(ApplicationUser user, MembershipStatus status)
    {
        User = user;
        Status = status;
    }

    [Required]
    public ApplicationUser User { get; private set; }

    [Required]
    public MembershipStatus Status { get; set; }

    [Required]
    public int Id { get; private set; }
}

其中ApplicationUser 是由 ASP MVC 5 成员基础结构生成的默认类。

当我运行我的测试 (Specflow),它为每个测试创建一个具有唯一 ID 的新 LocalDb 数据库并在该数据库上运行迁移时,实体框架会正确填充我的团队和所有者。

但是,当我运行网站并尝试与应用程序交互时,我的团队并没有完全填充,因为所有者是 null 并且 Members 没有填充。但是所有者 ID 在数据库中设置正确,并且查询似乎没问题。测试期间执行的查询和应用程序的运行看起来是一样的。

为什么会这样?我该如何开始调试问题?

我觉得我错过了一些简单的东西。

【问题讨论】:

    标签: entity-framework entity-framework-6


    【解决方案1】:

    您可能需要将.Include() 添加到您的查询中,这未在您的问题中显示,但应如下所示:

    var query = context.Teams.Include(x => x.Owner).Include(x => x.Members).Where( ... );
    

    EF 只会加载顶级实体,而不是它所引用的实体,直到需要它们(延迟加载)。如果您还没有释放上下文,那么简单地尝试访问这些导航属性应该会导致它们从数据库中加载,但如果上下文已被释放,则不会发生这种情况。

    .Include() 将通知 EF 这些导航属性需要与引用实体一起立即加载。

    请参阅this MSDN page 了解有关延迟/急切加载以及如何控制它的更多详细信息。

    【讨论】:

    • 谢谢史蒂夫。这似乎确实解决了问题。但是,对于为什么我的集成测试(在控制器上调用方法)有效并且具有完整填充的对象,我有点困惑。是因为上下文生命周期吗?我认为我的测试为测试的生命周期创建了一个上下文,这可能是几个控制器方法调用,并且在 IIS 中运行时 SimpleInjector 将为每个调用创建一个 DBContext。但是 dbcontext 不应该在加载团队和导航所有者/成员之间进行处理
    • 如果上下文尚未处理(并且实体仍附加到上下文),并且您访问导航属性,EF 应再次访问数据库以获取该实体。如果上下文被释放,这将不会发生。我将添加指向答案的链接以获取更多信息。
    • 除非明确分离,否则实体是否仍会附加到上下文?
    • 在 C# 6 中,您现在可以使用 nameof 来提高类型安全性。例如,.Include(nameof(Team.Owner))
    • 或者如果您使用的是较早的 EntityFramwork 版本,例如 v 4。var query = context.Teams.Include("Owner").Include("Members").Where( ... );
    猜你喜欢
    • 1970-01-01
    • 2017-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-21
    相关资源
    最近更新 更多