EF代码首先:一对许多关系更新导航对象



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

我有以下实体:

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

我有我的dbcontext as:

public class MyContext : DbContext
{
    public DbSet<Project> Projects { get; set; }
    public DbSet<Branch> Branches { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Branch>().HasMany<Project>(b => b.Projects).WithOptional(p => p.Branch).HasForeignKey(p => p.BranchId);
    }
}

从不同上下文中添加/更新/更新分支实体。项目成立没有分支,但是经过一些工作流程,需要将项目附加到分支列表中。

如果我尝试了,它可以正常工作:

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

,但是,如果我尝试过,我会得到一个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);
        }
    }

现在,我知道这是一种预期的行为,因为项目的分支属性没有初始化。,但我的问题是,如何在保存项目之前获得分支机构后更新分支(此时,该项目的某些处理仍然保留,因此无法保存仅仅是为了到达分支机构(。希望我能清楚地解释自己。

至少有两种实现目标的方法。

首先是通过使用DbReferenceEntry<TEntity, TProperty>.Load方法明确强制(RE(加载有关导航属性:

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

第二是强迫使用DbChangeTracker.DetectChanges方法更新所有修改的导航属性:

var project = db.Projects.Find(1);
project.BranchId = 8;
db.ChangeTracker.DetectChanges(); // <--
var branchName = project.Branch.Name;

这两种方法在您的情况下都可以使用,但是第一种方法更可靠 - 有或没有代理以及新实体(例如db.Projects.Add(。

最新更新