Tracking and DbContext Lifetime
Two deceptively simple questions expose whether you actually understand EF Core or just use it: "What does AsNoTracking do?" and "Why is my entity not saving?" Both are really questions about the change tracker and the DbContext lifetime, and interviewers love them because the confident-but-wrong answers are so common.
The change tracker in one breath
When a query materializes entities, the context takes a snapshot of each one. On
SaveChanges(), EF diffs current values against the snapshot and generates UPDATE statements
for what changed. That's the whole mechanism. From it, everything else follows:
AsNoTracking()skips the snapshot β faster reads, lower memory, but edits to those objects are invisible toSaveChanges(). Default for read-only screens.- Attach vs Add:
Addmarks the graphAdded(INSERT);Attachmarks itUnchangeduntil you flag properties modified. Interviewers probe this with disconnected-entity scenarios β an MVC edit form posts back a model that no context has ever seen.
A strong answer to "why is my entity not saving?" enumerates the causes aloud: the entity
came from an AsNoTracking query, it was loaded by a different context instance than the
one calling SaveChanges(), or SaveChanges() was never reached because of an early return
or swallowed exception. Then: "I'd check context.Entry(entity).State in the debugger."
Naming the diagnostic step is what separates the levels.
Context-per-request and the lifetime pitfalls
AddDbContext registers the context as scoped β one instance per HTTP request. Know why:
DbContext is cheap to create, not thread-safe, and its unit-of-work semantics map naturally
to one request. Then know the two classic pitfalls:
- Injecting a scoped context into a singleton (or a
BackgroundService) β it either throws or silently becomes an accidental singleton. The fix isIDbContextFactory<T>or creating a scope withIServiceScopeFactory. - Firing parallel queries on one context (
Task.WhenAllover two EF calls) β that's the "second operation started on this context" exception. One context, one operation at a time.
Answers that fall flat
- "AsNoTracking makes queries faster" with no idea why, or using it everywhere including update paths and then patching around the fallout.
- Making DbContext a singleton "for performance," or
using var context = new AppDbContext()scattered through controllers instead of DI. - Not knowing entities are unit-of-work-bound: loading in one context, saving in another, and being surprised.
Practice prompts
- Explain to an interviewer, in 60 seconds, how snapshot change tracking turns into an UPDATE.
- Sketch the disconnected-entity update for an MVC edit POST: load-then-map vs attach-and-mark.
- Describe how you'd use a DbContext safely inside a
BackgroundService, and why the naive injection fails.