Как Entity Framework отслеживает изменения в объектах и генерирует SQL запросы на обновление?
Что проверяют
Понимаете ли вы, что контекст хранит снимок загруженных данных, и знаете ли, когда отслеживание лучше отключить.
Как отвечать
DbContext содержит трекер изменений. При загрузке сущности он запоминает её исходные значения, а сам объект помечает состоянием Unchanged. Когда вы меняете свойство, объект остаётся тем же, но при вызове SaveChanges трекер сравнивает текущие значения с исходными и по разнице формирует UPDATE только для изменившихся колонок.
Состояния стоит перечислить: Added для новых объектов, Modified для изменённых, Deleted для удалённых, Unchanged и Detached для объектов вне контекста.
Дальше практические следствия, ради которых вопрос и задают:
- не нужен явный вызов
Updateдля загруженной сущности: достаточно изменить свойство и сохранить; AsNoTrackingотключает отслеживание для запросов только на чтение. На больших выборках это заметно быстрее и экономит память, потому что не создаются снимки;- отсоединённые объекты (пришедшие из веб-запроса) контекст не знает, поэтому их нужно присоединить и указать состояние, иначе изменения не сохранятся;
SaveChangesработает в транзакции и выполняет команды пакетом;- конкурентный доступ: колонка версии или признак совпадения исходных значений позволяют поймать чужое изменение и получить исключение вместо тихой перезаписи;
- длинный контекст это утечка: он держит все загруженные сущности, поэтому его делают короткоживущим, обычно на один запрос.
Где спотыкаются
Держат контекст статическим или на всё приложение и получают рост памяти вместе с устаревшими данными.
Забывают AsNoTracking в отчётных запросах.
Присваивают свойства отсоединённому объекту и удивляются, что SaveChanges ничего не сделал.