Можно ли отключить трекинг изменений в Entity Framework?

«Можно ли отключить трекинг изменений в Entity Framework?» — вопрос из категории Entity Framework, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, отключение отслеживания изменений (change tracking) в Entity Framework возможно и часто применяется для оптимизации производительности при операциях только для чтения.

Основные способы:

  1. AsNoTracking() для отдельного запроса:

    var users = await context.Users
        .AsNoTracking() // Сущности не отслеживаются контекстом
        .Where(u => u.IsActive)
        .ToListAsync();
  2. AsNoTrackingWithIdentityResolution() (EF Core 5+): Аналогичен AsNoTracking, но обеспечивает корректное разрешение циклических ссылок и дубликатов в графе объектов.

    var orders = context.Orders
        .Include(o => o.Customer)
        .AsNoTrackingWithIdentityResolution()
        .ToList();
  3. Глобальное отключение для контекста:

    context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
    // Все последующие LINQ-запросы будут выполняться без отслеживания

Практические сценарии и рекомендации:

  • Когда использовать: При построении отчетов, экспорте данных, операциях массового чтения или в веб-API, где сущности десериализуются в DTO и не возвращаются для модификации.
  • Производительность: Исключает накладные расходы на создание ChangeTracker-записей и проверку изменений, что экономит память и CPU.
  • Важное ограничение: Сущности, загруженные без отслеживания, не могут быть автоматически обновлены через SaveChanges(). Для обновления такой сущности её необходимо явно присоединить к контексту с состоянием Modified:
    var detachedUser = new User { Id = 1, Name = "Updated" };
    context.Users.Attach(detachedUser);
    context.Entry(detachedUser).State = EntityState.Modified;
    await context.SaveChangesAsync();