In this lesson, you will learn how EF Core’s "Change Tracker" consumes system memory and how to bypass it for high-performance read scenarios.
The Cost of Awareness
By default, when you retrieve an entity from the database, EF Core places it into the ChangeTracker. To enable this "magic" where EF Core detects changes for SaveChanges(), the tracker must maintain a snapshot of the original values for every property of every entity retrieved.
For small queries, this is negligible. However, if you are loading thousands of rows—such as generating a report or exporting data—the memory overhead grows linearly. The Change Tracker effectively doubles the memory footprint of your result set because it keeps both the current object and the "original value" snapshot in memory.
Mitigation: AsNoTracking()
When you know you are performing a read-only operation and do not intend to modify the data, you should explicitly instruct EF Core to skip the change tracking process. This is done using the AsNoTracking() extension method:
// High memory usage: every 'Order' is tracked
var trackedOrders = await context.Orders.ToListAsync();
// Low memory usage: EF Core skips snapshots
var readOnlyOrders = await context.Orders
.AsNoTracking()
.ToListAsync();
By using AsNoTracking(), EF Core creates the C# objects and populates them, but it immediately discards the tracking metadata. This significantly reduces the pressure on the Garbage Collector (GC) and allows your application to process larger graphs without triggering excessive memory allocation or latency spikes.
When to use it?
You should apply AsNoTracking() whenever:
- You are fetching data to display in a read-only UI.
- You are serializing data to JSON for an API response.
- You are performing bulk analysis where updates are not required.
If you find your application's memory usage climbing during query-heavy operations, AsNoTracking() is your primary tool for optimization. It shifts the balance back from "convenience" to "raw performance."
Key Takeaway: Disabling change tracking via AsNoTracking() is the most effective way to reduce memory consumption and improve throughput when your application only needs to read, not modify, database entities.