Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework POCO - Refresh a navigation property

I am having some trouble with refreshing the related collection of entities.

Essentially the problem is as follows:

public class Student
{
    public virtual ICollection<Lecture> Lectures { get; set; }

    public void AddLecture(Lecture lecture)
    {
        Lectures.Add(lecture);
    }

    public void CancelChanges()
    {
        _context.Refresh(RefreshMode.StoreWins, this);
        _context.LoadProperty(this, (o) => o.Lectures, 
            MergeOption.OverwriteChanges);
    }
}

public class Grade
{
    public virtual Student { get; set; }
}

Now I have some GUI for adding lectures and, if we want we can cancel the editing process:

public void ExampleEdit()
{
    Student student = _context.Students.SingleOrDefault(/* blah */);
    student.AddLecture(_context.Lectures.SingleOrDefault(/* e.g. math */));
    student.CancelChanges();
    // At this point student SHOULD have no lectures anymore since the 
    // property was loaded with overwrite changes option.
    // Yet the Lectures still contains the lecture we added there
}

So, is the code bad? Is there any method I use incorrectly? Is it possible to COMPLETELY reload the whole object?..

like image 512
Jefim Avatar asked Oct 01 '10 12:10

Jefim


1 Answers

I think you misunderstood MergeOption.OverwriteChanges. By default, anytime the ObjectContext performs a query, if any of the returned objects already exist in the cache the newly returned copies of those objects are ignored.

Please note that it all happens based on the EntityKeys. Basically the EntityKeys of the objects returned from a query are checked, and if an object with the same EntityKey (in the same EntitySet, in your case, Lectures) already exists in the cache, the existing object is left untouched.

However, if you enable OverwriteChanges, then it will Replace the current values of existing entities with values coming from the database, even if the in-memory entity has been edited.

As you can see you are adding a Lecture to the student that is totally new to Student and it will not be overwritten since its EntityKey is different than the ones that coming from database as per your LoadProperty() call.

One solution would be to just simply clear all the Lectures from your student object just before LoadProperty():

public void CancelChanges() {
    _context.Refresh(RefreshMode.StoreWins, this);
    this.Lectures.Clear();
    _context.LoadProperty(this, (o) => o.Lectures, MergeOption.OverwriteChanges);
}
like image 90
Morteza Manavi Avatar answered Nov 06 '22 14:11

Morteza Manavi