Entity Framework - Жизненный цикл

Продолжительность жизни

Время жизни контекста начинается при создании экземпляра и заканчивается, когда экземпляр либо удаляется, либо собирается сборщиком мусора.

  • Время жизни контекста - очень важное решение, которое необходимо принять, когда мы используем ORM.

  • Контекст работает как кеш сущностей, а это означает, что он содержит ссылки на все загруженные сущности, которые могут очень быстро расти в потреблении памяти, а также могут вызывать утечки памяти.

  • На диаграмме ниже вы можете увидеть верхний уровень потока операций с данными от приложения к базе данных через контекст и наоборот.

Жизненный цикл сущности

Жизненный цикл сущности описывает процесс, в котором сущность создается, добавляется, изменяется, удаляется и т. Д. Сущности имеют много состояний в течение своего жизненного цикла. Прежде чем смотреть, как получить состояние объекта, давайте посмотрим, что такое состояние объекта. Состояние - это перечисление типаSystem.Data.EntityState который декларирует следующие значения -

  • Added: Объект отмечен как добавленный.

  • Deleted: Сущность помечена как удаленная.

  • Modified: Сущность была изменена.

  • Unchanged: Сущность не была изменена.

  • Detached: Сущность не отслеживается.

Изменения состояния в жизненном цикле сущности

Иногда состояние сущностей устанавливается автоматически контекстом, но разработчик также может изменить его вручную. Хотя возможны все комбинации переключений из одного состояния в другое, но некоторые из них бессмысленны. Например,Added сущность к Deleted состояние или наоборот.

Давайте обсудим разные состояния.

Неизмененное состояние

  • Если объект не изменен, он привязан к контексту, но не был изменен.

  • По умолчанию объект, полученный из базы данных, находится в этом состоянии.

  • Когда сущность присоединяется к контексту (с помощью метода Attach), она точно так же находится в состоянии Unchanged.

  • Контекст не может отслеживать изменения в объектах, на которые он не ссылается, поэтому, когда они прикреплены, он предполагает, что они не изменились.

Обособленное состояние

  • Отсоединенный - это состояние по умолчанию для вновь созданной сущности, поскольку контекст не может отслеживать создание какого-либо объекта в вашем коде.

  • Это верно, даже если вы создаете экземпляр объекта внутри блока using контекста.

  • Отсоединено даже состояние сущностей, извлеченных из базы данных, когда отслеживание отключено.

  • Когда объект отсоединяется, он не привязан к контексту, поэтому его состояние не отслеживается.

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

  • Поскольку это не отслеживается контекстом, это не имеет значения для Entity Framework.

Добавленное состояние

  • Когда объект находится в состоянии «Добавлено», у вас есть несколько вариантов. Фактически, вы можете только оторвать его от контекста.

  • Естественно, даже если вы изменяете какое-либо свойство, состояние остается добавленным, потому что перемещение его в измененное, неизменное или удаленное не имеет смысла.

  • Это новая сущность, не имеющая соответствия ни одной строке в базе данных.

  • Это фундаментальная предпосылка для нахождения в одном из этих состояний (но это правило не обеспечивается контекстом).

Измененное состояние

  • Когда объект изменяется, это означает, что он находился в состоянии «Неизменено», а затем было изменено какое-то свойство.

  • После того, как объект переходит в состояние "Изменено", он может перейти в состояние "Отсоединено" или "Удалено", но не может вернуться в состояние "Не изменено", даже если вы вручную восстановите исходные значения.

  • Его даже нельзя изменить на «Добавлено», если вы не отсоедините и не добавите объект в контекст, потому что строка с этим идентификатором уже существует в базе данных, и вы получите исключение времени выполнения при ее сохранении.

Удаленное состояние

  • Сущность переходит в состояние «Удалено», так как она была «Неизменена» или «Изменена», а затем был использован метод DeleteObject.

  • Это наиболее ограничивающее состояние, потому что бессмысленно переходить из этого состояния в любое другое значение, кроме Detached.

В using, если вы хотите, чтобы все ресурсы, которыми управляет контекст, располагались в конце блока. Когда вы используетеusing оператор, то компилятор автоматически создает блок try / finally и вызывает dispose в блоке finally.

using (var context = new UniContext()) {

   var student = new Student {
      LastName = "Khan", 
      FirstMidName = "Ali", 
      EnrollmentDate = DateTime.Parse("2005-09-01")
   };

   context.Students.Add(student);
   context.SaveChanges();
}

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

  • По мере загрузки в память большего количества объектов и их ссылок потребление памяти контекстом может быстро увеличиваться. Это может вызвать проблемы с производительностью.

  • Не забудьте избавиться от контекста, когда он больше не нужен.

  • Если исключение приводит к тому, что контекст находится в неустранимом состоянии, все приложение может завершиться.

  • Вероятность возникновения проблем, связанных с параллелизмом, увеличивается по мере увеличения промежутка между запросом и обновлением данных.

  • При работе с веб-приложениями используйте экземпляр контекста для каждого запроса.

  • При работе с Windows Presentation Foundation (WPF) или Windows Forms используйте экземпляр контекста для каждой формы. Это позволяет использовать функцию отслеживания изменений, предоставляемую контекстом.

Эмпирические правила

Web Applications

  • В настоящее время общепринятой практикой является то, что для веб-приложений контекст используется для каждого запроса.

  • В веб-приложениях мы имеем дело с очень короткими запросами, которые содержат все серверные транзакции, поэтому они являются надлежащей продолжительностью для существования контекста.

Desktop Applications

  • Для настольных приложений, таких как Win Forms / WPF и т. Д., Контекст используется для формы / диалога / страницы.

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

  • Таким образом, мы получим множество возможностей контекста и не будем страдать от последствий длительных контекстов.