Phase 26 of 30 · Topic 26.1

EF Core Change Tracker Internals & `AsNoTracking()` Optimization

1Concept

The EF Core Change Tracker maintains snapshots of all loaded entities to detect property changes for `SaveChanges()`. For read-only queries, `.AsNoTracking()` bypasses tracking snapshots, saving 50%+ memory and CPU cycles.

2Architecture Diagram

Query with Tracking (Default):
Database Query ──> Materialize Entity ──> Create Snapshot in ChangeTracker ──> Return Entity

Query with AsNoTracking():
Database Query ──> Materialize Entity ──> Return Entity (Zero Tracker Overhead!)

3Code Example

C# 13 & .NET 9
using System;

public class EfTrackingConceptDemo
{
    public static void Main()
    {
        Console.WriteLine("Read-only query optimization:");
        Console.WriteLine("var activeUsers = await context.Users");
        Console.WriteLine("    .AsNoTracking()");
        Console.WriteLine("    .Where(u => u.IsActive)");
        Console.WriteLine("    .ToListAsync();");
    }
}

4Expected Output

Read-only query optimization:
var activeUsers = await context.Users
    .AsNoTracking()
    .Where(u => u.IsActive)
    .ToListAsync();

5Key Takeaways

  • Always use `.AsNoTracking()` on queries that only read data for UI or API responses.
  • Use `AsNoTrackingWithIdentityResolution()` when querying complex cyclic graphs without tracking.
  • Significantly reduces memory footprint in large batch queries.