Entity Framework 与 ASP.NET 一对多关系导致 NullReference 错误

Entity Framework with ASP.NET one-to-many relation causes NullReference error

在我的数据库中有两个实体:DbStatus 和 DbTask

public class DbStatus
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<DbTask> Tasks { get; set; }
}

public class DbTask
{
    public int Id { get; set; }
    public string Title { get; set; }
    public bool Done { get; set; }
    public int StatusId { get; set; }
    public virtual DbStatus Status { get; set; }
}

OnModelCreating方法中,我用下面的代码建立关系:

modelBuilder.Entity<DbStatus>()
            .HasMany(s => s.Tasks)
            .WithOne(t => t.Status)
            .HasForeignKey(t => t.StatusId);

我也在这个方法中添加了一些示例数据,设置新创建的DbTasksStatusId

问题是,当我尝试使用

访问 DbTaskStatus 名称时
task.Status.Name

我得到一个NullReferenceException

谁能帮我正确设置关系?

重要

对于阅读本文的任何人,Rob 提供了最快的解决方案(以及满足特定任务标准的解决方案)。但是,您应该阅读并实施 Steve Py 提供的解决方案,原因在他们的回答中也有所描述!

从数据库中获取 DbTasks 的列表时,您需要告诉它包含子 Status 对象。

尝试这样的事情:

var tasks = dbContext.DbTasks
    .Include(t => t.Status)
    .ToList();

在实体上设置 FK 不会自动导致加载相关实体。使用导航属性时,我建议避免在实体中声明 FK 字段并使用影子属性来避免此类问题。

要更新 DbTask 的状态:

public ActionResult MarkTaskComplete(int taskId)
{
    var completeStatus = _context.Statuses.Single(x => x.StatusId = Statuses.Complete);
    // TODO: Validation that user can update task etc.
    var task = _context.Tasks
        .Include(x => x.Status)
        .Single(x => x.TaskId == taskId);
    task.Status = completeStatus;
    _context.SaveChanges();
    return Json(new { success = true; status = task.Status.Name } );
}

FK 字段的问题是行为可能会有所不同,具体取决于您是使用导航 属性 还是 FK,以及导航 属性 是否预先加载。从任务的角度来看,当前状态有两个真实来源,一些代码可能会检查 task.StatusId,而另一些代码会使用 task.Status.StatusId。这些值可能会有所不同,具体取决于在没有更新另一个的情况下更新一个值。

虽然这可能意味着访问数据库以获取状态,但通过 ID 获取行非常快,并且还可以验证您的方法是否仅使用合法值。