Entity Framework POCO - обновить свойство навигации - PullRequest
5 голосов
/ 01 октября 2010

У меня возникли проблемы с обновлением связанной коллекции сущностей.

По сути, проблема заключается в следующем:

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

Теперь у меня есть некоторый графический интерфейс для добавления лекций, и, если мы хотим, мы можем отменить процесс редактирования:

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 голосов
/ 02 октября 2010

Я думаю, вы неправильно поняли MergeOption.OverwriteChanges . По умолчанию каждый раз, когда ObjectContext выполняет запрос, если какой-либо из возвращенных объектов уже существует в кэше, вновь возвращенные копии этих объектов игнорируются.

Обратите внимание, что все это происходит на основе EntityKeys . В основном проверяются EntityKeys объектов, возвращаемых из запроса, и если объект с такой же EntityKey (в том же EntitySet, в вашем случае, Lectures ) уже существует в кэше, существующий объект остается нетронутым.

Однако, если вы включите OverwriteChanges , тогда он будет Заменить текущие значения существующих объектов на значения, поступающие из базы данных, даже если объект в памяти имеет был отредактирован.

Как вы можете видеть, вы добавляете Лекцию для студента, которая является совершенно новой для Студента, и она не будет перезаписана, поскольку ее EntityKey отличается от тех, которые поступают из базы данных в соответствии с вашим вызовом LoadProperty () .

Одним из решений было бы просто очистить все лекции от вашего студенческого объекта непосредственно перед LoadProperty () :

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