Entity Framework - Зачем явно устанавливать состояние объекта для изменения? - PullRequest
42 голосов
/ 18 августа 2011

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

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

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

dpt.Name = "Blah"

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

Ответы [ 2 ]

44 голосов
/ 18 августа 2011

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

23 голосов
/ 14 июня 2015

Как уже говорилось, в сценарии с отключенными объектами может быть полезно установить состояние объекта на 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...