Tutorials ASP.NET Core MVC Mastery

DbContext

On this page

DbContext in EF Core — The Heart of Data Access

In Entity Framework Core, the DbContext is the absolute center of your data universe. It represents a session with the database, handling database connections, querying, change tracking, and saving data. Understanding its architecture and lifecycle is the difference between a high-performance application and one plagued by memory leaks.

1. WHAT is DbContext?

A DbContext is a combination of the Unit of Work and Repository patterns. It acts as a bridge between your C# entity classes and the relational database.

  • Unit of Work: Tracks changes made to entities during the lifetime of the context and commits them all in a single transaction via SaveChanges().
  • Repository (DbSet): Exposes `DbSet<TEntity>` properties, which act as collections of your entities, allowing you to query them using LINQ.

2. REAL-TIME PRODUCTION EXAMPLE

Step 1: Creating the ApplicationDbContext

Never use the base DbContext directly. Always inherit from it to create your domain-specific context.

using Microsoft.EntityFrameworkCore;

public class ApplicationDbContext : DbContext
{
    // The constructor accepts options (connection strings, providers) 
    // passed down from Dependency Injection in Program.cs
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) 
        : base(options) 
    { 
    }

    // 1. Define Repositories (DbSets)
    public DbSet<Customer> Customers { get; set; }
    public DbSet<Order> Orders { get; set; }
    public DbSet<Product> Products { get; set; }

    // 2. Configure Schema using the Fluent API
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // Instead of polluting entities with [Attributes], 
        // enterprise apps use Fluent API for strict control.
        modelBuilder.Entity<Product>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.Property(e => e.Name).IsRequired().HasMaxLength(200);
            entity.Property(e => e.Price).HasPrecision(18, 2); // Extremely important for money!
        });

        // Best Practice: Moving configurations into separate classes
        // modelBuilder.ApplyConfigurationsFromAssembly(typeof(ApplicationDbContext).Assembly);
    }
}

Step 2: Registration in Program.cs

In ASP.NET Core, the DI container manages the lifecycle of the DbContext.

// Read connection string from appsettings.json
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");

// Register as Scoped by default
builder.Services.AddDbContext<ApplicationDbContext>(options =>
{
    // Configure the database provider (SQL Server, PostgreSQL, etc.)
    options.UseSqlServer(connectionString, sqlOptions => 
    {
        // Enterprise setting: Automatically retry on transient network failures
        sqlOptions.EnableRetryOnFailure(
            maxRetryCount: 3,
            maxRetryDelay: TimeSpan.FromSeconds(5),
            errorNumbersToAdd: null);
    });
    
    // Developer helper: Log SQL queries to console (dev only)
    if (builder.Environment.IsDevelopment())
    {
        options.EnableSensitiveDataLogging(); 
        options.LogTo(Console.WriteLine, LogLevel.Information);
    }
});

3. The DbContext Lifecycle (Critical)

How long should a DbContext live? The answer dictates your application's architecture.

Transient

A new instance is created every time it is requested. Bad idea. Change tracking breaks down because different services injected into the same request get different contexts.

Scoped (Standard)

One instance is created per HTTP request. Perfect for web apps. All services within that request share the same context and share the same transaction upon SaveChanges().

Singleton

One instance for the entire application lifetime. Disastrous. DbContext is not thread-safe. Concurrent requests will crash the application.

4. DbContextPooling (High Performance)

Creating and disposing a DbContext takes CPU cycles. If your app handles high traffic, you can "pool" contexts. When a request ends, the context is reset and returned to a pool rather than being destroyed and garbage collected.

// Instead of AddDbContext, use AddDbContextPool
builder.Services.AddDbContextPool<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString)
);

5. Best Practices & Pitfalls

  • Use Fluent API over Data Annotations: Keep your domain models pure. Place database-specific configurations (like composite keys or index strategies) in OnModelCreating.
  • Don't inject DbContext into Singletons: Background services (IHostedService) are Singletons. If you inject a Scoped DbContext into them, the app crashes. Instead, use IDbContextFactory<T> to spawn contexts on demand.
  • Call SaveChangesAsync() ONCE: The DbContext tracks multiple inserts/updates. Don't call SaveChanges in a loop. Do the loop, then call SaveChanges once to batch the SQL queries into a single transaction.

6. Interview Mastery

Q: "Why would you use IDbContextFactory instead of standard Dependency Injection?"

Architect Answer: "Standard DI registers DbContext as a Scoped service, meaning it is tied to the lifespan of an HTTP Request. But what if there is no HTTP request? In background workers (like a RabbitMQ consumer or an `IHostedService`), the service is a Singleton. Injecting a Scoped DbContext into a Singleton is an anti-pattern that creates a memory leak and concurrency crashes because DbContext isn't thread-safe. In those scenarios, I inject `IDbContextFactory`. The background service uses the factory to manually spawn `using (var context = _factory.CreateDbContext())` — performing its work in a safe, isolated, and properly disposed context."

Questions on this lesson 0

Sign in to ask a question or upvote helpful answers.

No questions yet — be the first to ask!

ASP.NET Core MVC Mastery
Course syllabus
1. Core Framework
MODULE 1: INTRODUCTION & ENVIRONMENT SETUP
2. View Engine
MODULE 2: .NET CORE FUNDAMENTALS
MODULE 3: ASP.NET CORE BASICS
MODULE 4: MVC FUNDAMENTALS
MODULE 5: DATA PASSING TECHNIQUES
MODULE 6: ROUTING
MODULE 7: VIEWS & UI
MODULE 8: ACTION RESULTS
MODULE 9: HTML HELPERS
MODULE 10: TAG HELPERS
MODULE 11: MODEL BINDING
MODULE 12: VALIDATION
MODULE 13: STATE MANAGEMENT
MODULE 14: FILTERS & SECURITY
MODULE 15: ENTITY FRAMEWORK CORE (DEEP DIVE)
MODULE 16: DESIGN PATTERNS
MODULE 17: FILE HANDLING
MODULE 18: ADVANCED ASP.NET CORE
MODULE 19: PERFORMANCE & BEST PRACTICES
MODULE 20: RAZOR PAGES (BONUS)
MODULE 21: REAL-WORLD PROJECTS (🔥 MUST DO)
Toolliyo Assistant
Ask about tutorials, ebooks, training, pricing, mentor services, and support. I use public site content only—not admin or internal tools.

care@toolliyo.com

Need callback? Share your details