Entity framework EF代码优先:一对多关系更新导航对象

Entity framework EF代码优先:一对多关系更新导航对象,entity-framework,ef-code-first,dbcontext,Entity Framework,Ef Code First,Dbcontext,让我通过一个例子来解释我的问题: 我拥有以下实体: public class Project { public int ProjectId { get; set; } public string ProjectName { get; set; } public int? BranchId { get; set; } public virtual Branch Branch { get; set; } } public class Branch { pu

让我通过一个例子来解释我的问题:

我拥有以下实体:

public class Project
{
    public int ProjectId { get; set; }
    public string ProjectName { get; set; }

    public int? BranchId { get; set; }
    public virtual Branch Branch { get; set; }
}

public class Branch
{
    public int BranchId { get; set; }
    public string BranchName { get; set; }

    public virtual ICollection<Project> Projects { get; set; }

    public Branch()
    {
        Projects = new ObservableCollection<Project>();
    }
}
但是,如果我尝试此操作,会得到一个NullReference异常:

    private void ForeignKeyTest()
    {
        using (var db = new MyContext())
        {
            var project = db.Projects.Find(1);
            project.BranchId = 8;

            var msg = project.Branch.BranchName; //call to the Branch before save

            db.SaveChanges();

            MessageBox.Show(msg);
        }
    }

现在,我理解这是一种预期行为,因为项目的分支属性尚未初始化但我的问题是,在保存项目之前,如何在获取BranchHid后强制更新分支(此时仍保留对项目的某些处理,因此不能仅保存以获取分支)。希望我解释清楚

实现目标至少有两种方法

首先,通过使用以下方法明确强制(重新)加载有问题的导航属性:


这两种方法都适用于您的场景,但第一种方法更可靠—无论是否使用代理,也适用于新实体(例如
db.Projects.Add
)。

嗨,伊万·斯托夫!谢谢你的回答。这两种选择都非常有效。不过,我还有一个问题。如果我只能公开访问存储库的DbSet属性(它隐藏了DbContext),那么可以实现同样的功能吗?不幸的是,您需要访问
DbContext
,并且
DbSet
不公开它绑定到的
DbContext
(尽管它内部有引用)。相反,我认为可以添加一个方法“DetectChanges()“到我的存储库,存储库将调用它作为受保护属性保存的DbContext上的相同方法。我不想向调用代码公开DbContext。可以接受吗?对我有用:)嗨,伊万·斯托夫。在对您的编辑进行了思考,认为第一个选项更可靠之后,我在我的基本存储库中提出了以下内容,但需要测试。请看一看并发表评论public void LoadChild(T entity,Expression child),其中TChild:persistenententity{Db.Entry(entity).Reference(child.Load();}'
    private void ForeignKeyTest()
    {
        using (var db = new MyContext())
        {
            var project = db.Projects.Find(1);
            project.BranchId = 8;

            db.SaveChanges();

            var msg = project.Branch.BranchName; //call to the Branch after save

            MessageBox.Show(msg);
        }
    }
    private void ForeignKeyTest()
    {
        using (var db = new MyContext())
        {
            var project = db.Projects.Find(1);
            project.BranchId = 8;

            var msg = project.Branch.BranchName; //call to the Branch before save

            db.SaveChanges();

            MessageBox.Show(msg);
        }
    }
var project = db.Projects.Find(1);
project.BranchId = 8;
db.Entry(project).Reference(e => e.Branch).Load(); // <--
var branchName = project.Branch.Name;
var project = db.Projects.Find(1);
project.BranchId = 8;
db.ChangeTracker.DetectChanges(); // <--
var branchName = project.Branch.Name;