Ответ
Change Tracking — это фундаментальный механизм в Entity Framework Core, который автоматически отслеживает изменения, происходящие с сущностями, привязанными к экземпляру DbContext. При вызове SaveChanges() EF генерирует и выполняет необходимые SQL-команды (INSERT, UPDATE, DELETE) на основе этих отслеженных изменений.
Как это работает на практике:
- Загрузка и отслеживание: Когда сущность загружается через контекст (например,
Find(),ToList()безAsNoTracking()), EF начинает отслеживать ее, запоминая исходные значения свойств (снимок состояния). - Обнаружение изменений: При изменении свойств сущности контекст фиксирует это. Вы можете явно проверить изменения через
context.ChangeTracker.HasChanges(). - Синхронизация с БД: При вызове
SaveChanges()EF сравнивает текущие значения с исходными, определяет, какие сущности были добавлены, изменены или удалены, и формирует пакет команд для БД.
Пример:
using (var db = new AppDbContext())
{
// Сущность загружается и начинает отслеживаться
var blog = db.Blogs.Find(1);
// Изменение свойства отслеживается
blog.Rating = 5;
// Добавление новой отслеживаемой сущности
db.Posts.Add(new Post { Title = "New Post" });
// На этом этапе EF знает, что нужно:
// - UPDATE для Blogs (изменен Rating)
// - INSERT для Posts (добавлен новый Post)
db.SaveChanges(); // Команды отправляются в БД
}
Ключевые моменты и управление:
- Производительность: Отслеживание требует памяти и процессорного времени. Для сценариев "только чтение" используйте
AsNoTracking()илиAsNoTrackingWithIdentityResolution(). - Отслеживание по умолчанию: Работает для сущностей, полученных из контекста, а также для вновь добавленных (
Add,AddRange). - Ручное управление состоянием: Вы можете явно указать состояние сущности через
db.Entry(entity).State = EntityState.Modified(илиAdded,Deleted,Unchanged,Detached). Это полезно при работе с отключенными сущностями (например, из веб-запроса). - Detached: Состояние
Detachedозначает, что контекст больше не отслеживает сущность.