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
}

那么,代码不好吗?有什么方法我使用不正确吗?是否可以完全重新加载整个对象?..

4

1 回答 1

7

我认为您误解了 MergeOption.OverwriteChanges。默认情况下,只要ObjectContext执行查询,如果任何返回的对象已经存在于缓存中,则这些对象的新返回副本将被忽略。

请注意,这一切都是基于EntityKeys发生的。基本上检查从查询返回的对象的 EntityKeys,如果缓存中已经存在具有相同EntityKey 的对象(在同一个 EntitySet 中,在您的情况下为Lectures),则现有对象保持不变。

但是,如果您启用OverwriteChanges,那么它将替换具有来自数据库的值的现有实体的当前值,即使内存中的实体已被编辑。

如您所见,您正在向学生添加一个 Lecture,这对 Student 来说是全新的,并且不会被覆盖,因为它的 EntityKey 与根据您的LoadProperty()调用来自数据库的不同。 一种解决方案是在LoadProperty()

之前简单地清除学生对象中的所有 Lectures :

public void CancelChanges() {
    _context.Refresh(RefreshMode.StoreWins, this);
    this.Lectures.Clear();
    _context.LoadProperty(this, (o) => o.Lectures, MergeOption.OverwriteChanges);
}
于 2010-10-01T20:02:34.087 回答