当我更改Id时,EF导航属性似乎没有更新

时间:2012-12-12 16:00:12

标签: .net entity-framework

我有以下课程:

public class Person {
   public int Id {get; set;}
   ...
   public ICollection<PersonalJobs> Jobs {get; set;}
}

public class PersonalJob {
   public int Id {get; set;}
   public int PersonId {get; set;}
   public int JobId {get; set;}
   public Job Job {get; set;}
   public DateTime StartDate {get; set;}
   ...
}

public class Job {
   public int Id {get; set;}
   public string Description {get; set;}
   ...
}

现在我执行以下操作:

var _personId = 1;
var _jobId = 15;

_context.Set<Jobs>().Load();  //Pre-Load all jobs

var _person = _context.Persons.Include(p => p.Jobs.Select(j => j.Job))
   .SingleOrDefault(p => p.Id == _personId);

var _job = _person.Jobs.SingleOrDefault(p => p.JobId == _jobId);
_job.JobId = 23;  //Change the job that this person is tied to.

// At this point, if I try to access _job.Job.Description, it still references the old job.

因为上下文已经加载了Jobs,所以我假设当我更改ID时,EF会更新_job的导航属性。然而,这种情况并非如此。在这种情况下,_job.Job仍然引用与原始Id(15)相关联的作业。

我假设EF如何处理导航属性,或者我只是错过了这个难题中的一块,我错了吗?

感谢。

2 个答案:

答案 0 :(得分:1)

您需要调用SaveChanges()来持久保存到数据库:

_job.JobId = 23;

_context.SaveChanges();

// _job.Job now points to Job 23

这仅适用,因为作业23已加载到您的DbContext

如果加载了某个对象,EF会在您拨打SaveChanges()

时挂断您的媒体资源

修改

您已加载所有作业,因此您可以自行设置该属性:

_job.Job = _context.Set<Jobs>().Find( 23 );

这不会导致任何数据库调用 - 您的DbContext

会满足

当您拨打UPDATE

时,会产生相同的SaveChanges()语句

答案 1 :(得分:1)

我刚刚在您的评论中读到您希望引用在保存之前与新ID 同步。但这是EF不会自动完成的事情。当你打电话给SaveChanges时会发生这种情况,但是如果你想在此之前发生这种情况,你必须致电

_context.ChangeTracker.DetectChanges();

(假设您使用DbContext API)

DetectChanges触发 relationship fixup ,这是一个同步外键中涉及的所有属性的进程。

顺便说一句:你没有必要预先加载工作才能成功。