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 и т. Д., Контекст используется для формы / диалога / страницы.
Поскольку мы не хотим иметь контекст в качестве синглтона для нашего приложения, мы избавимся от него при переходе от одной формы к другой.
Таким образом, мы получим множество возможностей контекста и не будем страдать от последствий длительных контекстов.