Entity Framework - Почему явным образом задал состояние объекта для изменения?

В официальной документации говорится, что для изменения объекта я получаю объект DbEntityEntry и либо работаю с функциями свойств, либо я изменяю его состояние. Он использует следующий пример

Department dpt = context.Departments.FirstOrDefault();
DbEntityEntry entry = context.Entry(dpt);
entry.State = EntityState.Modified;

Я не понимаю цели второго и третьего высказываний. Если я попрошу структуру для сущности, такой как 1-й оператор, а затем изменить POCO, как в

dpt.Name = "Blah"

Если я затем спрошу EF на SaveChanges(), объект имеет статус MODIFIED (я предполагаю, что отслеживание моментальных снимков, это не прокси-сервер), и изменения сохраняются без необходимости вручную устанавливать состояние. Я что-то пропустил?

Ответ 1

В вашем сценарии вам действительно не нужно устанавливать состояние. Цель отслеживания изменений заключается в том, что вы изменили значение на прикрепленном объекте и перевели его в измененное состояние. Настройка состояния вручную важна в случае отдельных объектов (объектов, загруженных без отслеживания изменений или созданных за пределами текущего контекста).

Ответ 2

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

Но могут быть очень веские причины не устанавливать состояние Modified (и я уверен, что Ладислав знал об этом, но все же я хотел бы указать их здесь).

  1. Будут обновлены все поля в записи, а не только изменения. Есть много систем, в которых обновления проверяются. Обновление всех полей приведет либо к большому количеству помех, либо потребует, чтобы механизм аудита отфильтровал ложные изменения.

  2. Оптимистичный параллелизм. Поскольку все поля обновлены, это может вызвать больше конфликтов, чем необходимо. Если два пользователя одновременно обновляют одни и те же записи, но не одни и те же поля, конфликт не должен возникать. Но если они всегда обновляют все поля, последний пользователь всегда будет пытаться записать устаревшие данные. В лучшем случае это вызовет исключение оптимистичного параллелизма или в худшем случае потерю данных.

  3. Бесполезные обновления. Сущность помечена как измененная, несмотря ни на что. Неизмененные объекты также будут запускать обновление. Это может легко произойти, если окна редактирования могут быть открыты, чтобы видеть детали и закрыты OK.

Так что это прекрасный баланс. Уменьшите количество обращений или уменьшите избыточность.

В любом случае, альтернативой для установки состояния Modified является (использование DbContext API):

void UpdateDepartment(Department department)
{
    var dpt = context.Departments.Find(department.Id);
    context.Entry(dpt).CurrentValues.SetValues(department);
    context.SaveChanges();
}

CurrentValues.SetValues помечает отдельные свойства как Modified.

Или присоедините отключенную сущность и пометьте отдельные свойства как Modified вручную:

context.Entry(dpt).State = System.Data.Entity.EntityState.Unchanged;
context.Entry(dpt).Property(d => d.Name).IsModified = true;