DEV Community

Libin Tom Baby
Libin Tom Baby

Posted on

Dependency Injection Lifetime for DbContext in .NET: Choosing the Right Scope


Which DI Lifetime to Use for DbContext?

If you’ve worked with Entity Framework Core, you’ve probably seen the classic interview question:

“What lifetime should you use for DbContext — Scoped, Transient, or Singleton?”

The correct answer is Scoped, but understanding why is what separates a junior developer from a senior engineer.

This guide explains the reasoning, the internals, and real-world scenarios so you can answer confidently in interviews and write safer, more scalable applications.


What Is DbContext?

DbContext represents a unit of work and a session with the database.

It:

  • Tracks changes
  • Manages entity states
  • Handles database connections
  • Executes queries
  • Saves changes

Because it tracks state, its lifetime matters.


The Three DI Lifetimes in .NET

Before choosing the right one, here’s a quick refresher:

Transient

A new instance every time it’s requested.

Scoped

One instance per HTTP request.

Singleton

One instance for the entire application lifetime.


Why DbContext Should Be Scoped

✔️ 1. DbContext is not thread-safe

ASP.NET Core handles multiple requests concurrently.

If you use a Singleton DbContext, multiple threads will share the same instance.

This leads to:

  • Race conditions
  • Corrupted state
  • Random exceptions
  • Broken change tracking

✔️ 2. Scoped matches the unit-of-work pattern

Each HTTP request represents a business operation.

Examples:

  • Creating an order
  • Updating a profile
  • Processing a payment

A scoped DbContext ensures:

  • One context per operation
  • One transaction per request
  • Clean change tracking
  • Predictable behavior

✔️ 3. Scoped ensures proper connection management

DbContext opens and closes connections efficiently within the request scope.


Why NOT Transient?

Transient creates a new DbContext every time it’s injected.

This causes:

❌ Multiple DbContexts in the same request

You may accidentally:

  • Query with one context
  • Save with another
  • Lose change tracking
  • Break transactions

❌ Hard-to-debug inconsistencies

Different DbContexts don’t share state.


Why NOT Singleton?

Singleton is the worst possible choice.

❌ DbContext is not thread-safe

Multiple requests → shared instance → chaos.

❌ Memory leaks

The context keeps tracking more and more entities.

❌ Stale data

Long-lived DbContexts cache query results.

❌ Broken transactions

A single DbContext cannot manage multiple concurrent operations.


Real‑World Scenarios

Scenario 1: Web API request

User updates their profile.

  • One request
  • One DbContext
  • One transaction

Use Scoped


Scenario 2: Background service

A hosted service processes messages from a queue.

Each message should have its own DbContext.

using var scope = _serviceProvider.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
Enter fullscreen mode Exit fullscreen mode

Use Scoped inside a created scope


Scenario 3: Console app

Short-lived operations.

Transient or Scoped both work, but Scoped is still preferred for consistency.


How to Register DbContext Correctly

services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(Configuration.GetConnectionString("Default")));
Enter fullscreen mode Exit fullscreen mode

This registers DbContext as Scoped by default.


Interview‑Ready Summary

  • DbContext should be Scoped
  • DbContext is not thread-safe
  • Scoped aligns with unit-of-work
  • Singleton causes race conditions and memory leaks
  • Transient causes multiple contexts per request

A clean, senior-level answer:

“DbContext should be registered as Scoped because it represents a unit of work per request, is not thread-safe, and must not be shared across concurrent operations. Transient creates too many contexts, and Singleton causes concurrency issues and stale tracking.”


Top comments (0)