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
(и я уверен, что Ладислав знал об этом, но все же я хотел бы указать их здесь).
-
Будут обновлены все поля в записи, а не только изменения. Есть много систем, в которых обновления проверяются. Обновление всех полей приведет либо к большому количеству помех, либо потребует, чтобы механизм аудита отфильтровал ложные изменения.
-
Оптимистичный параллелизм. Поскольку все поля обновлены, это может вызвать больше конфликтов, чем необходимо. Если два пользователя одновременно обновляют одни и те же записи, но не одни и те же поля, конфликт не должен возникать. Но если они всегда обновляют все поля, последний пользователь всегда будет пытаться записать устаревшие данные. В лучшем случае это вызовет исключение оптимистичного параллелизма или в худшем случае потерю данных.
-
Бесполезные обновления. Сущность помечена как измененная, несмотря ни на что. Неизмененные объекты также будут запускать обновление. Это может легко произойти, если окна редактирования могут быть открыты, чтобы видеть детали и закрыты 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;