实体框架 POCO - 刷新导航属性

5

我在刷新相关实体集合方面遇到了一些问题。

问题本质上如下:

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

现在我有一些用于添加讲座的GUI,如果需要,我们可以取消编辑过程:
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
}

那么,这段代码有问题吗?我是否使用了错误的方法?是否可能完全重新加载整个对象?

1个回答

7

我认为你误解了MergeOption.OverwriteChanges。默认情况下,任何时候ObjectContext执行查询,如果返回的任何对象已经存在于缓存中,则这些对象的新副本将被忽略。
请注意,这一切都是基于EntityKeys进行的。基本上,从查询返回的对象的EntityKeys会被检查,如果在缓存中已经存在具有相同EntityKey(在同一个EntitySet中,在您的情况下是Lectures)的对象,则现有对象将不受影响。
但是,如果启用了OverwriteChanges,则它将使用来自数据库的值替换现有实体的当前值,即使内存中的实体已被编辑。
正如您所看到的,您正在向完全新的Student添加一个Lecture,由于其EntityKey与通过LoadProperty()调用获取的EntityKey不同,因此它不会被覆盖。
解决方案之一是在LoadProperty()之前简单地清除student对象中的所有Lectures:
public void CancelChanges() {
    _context.Refresh(RefreshMode.StoreWins, this);
    this.Lectures.Clear();
    _context.LoadProperty(this, (o) => o.Lectures, MergeOption.OverwriteChanges);
}

非常感谢您的解释 - 它让我头脑中的很多事情变得更加清晰。您提出的解决方案非常方便 - 我刚刚更新了我的代码,事实上它确实起作用了。 - Jefim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接