Reputation: 11167
I have the following classes:
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;}
...
}
Now I do something like the following:
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.
Because the context already had Jobs loaded, I assumed that EF would update the navigation property of _job when I change the ID. However, this is not the case. In this case _job.Job still references the job associated with the original Id (15).
Am I wrong in my assumption of how EF handles navigation properties or am I just missing a piece in this puzzle?
Thanks.
Upvotes: 1
Views: 646
Reputation: 24383
You need to call SaveChanges()
to persist to the database:
_job.JobId = 23;
_context.SaveChanges();
// _job.Job now points to Job 23
This only works because Job 23 is already loaded into your DbContext
.
If an object is loaded, EF will hook up your property when you call SaveChanges()
EDIT:
You've loaded all the Jobs, so you could just set the property yourself:
_job.Job = _context.Set<Jobs>().Find( 23 );
This won't result in any database calls - it will be satisfied from your DbContext
It will result in the same UPDATE
statement when you do call SaveChanges()
Upvotes: 1
Reputation: 109080
I just read in your comment you want the reference to be in sync with the new id before saving. But that is something that EF does not do automatically. It happens when you call SaveChanges
allright, but if you want it to happen before that you have to call
_context.ChangeTracker.DetectChanges();
(Assuming that you use the DbContext
API)
DetectChanges
triggers relationship fixup which is a process that synchronizes all properties involved in foreign keys.
BTW: you don't have to preload the jobs for this to succeed.
Upvotes: 2