Using Multiple EF Core DbContexts In a Single Application

Using Multiple EF Core DbContexts In a Single Application

5 min read ·

Thank you to our sponsors who keep this newsletter free to the reader:

Today's issue is sponsored by Hasura, an open-source engine that gives instant GraphQL and REST APIs on new or existing SQL Server, enabling teams to ship apps faster.

And by Localizely, the translation management platform that helps you translate texts in your app for targeting multilingual markets.

Entity Framework Core (EF Core) is a popular ORM in .NET that allows you to work with SQL databases. EF Core uses a DbContext, which represents a session with the database and is responsible for tracking changes, performing database operations, and managing database connections.

It's common to have only one DbContext for the entire application.

But what if you need to have multiple DbContexts?

In this week's newsletter we're going to explore:

  • When you may want to use multiple DbContexts
  • How to create multiple DbContexts
  • What are the benefits of using multiple DbContexts

Let's dive in!

Why Use Multiple DbContexts?

There are a few cases where using multiple DbContexts can be useful.

Multiple Databases
Does your application need to work with multiple SQL databases? Then you're forced to use multiple DbContexts, each one dedicated to a specific SQL database.

Separating Concerns
If the application you're building has a complex domain model, you may see an improvement by separating concerns between a few DbContexts, where each one is responsible for a specific area of the domain model.

Modular Monolith
When you're building a Modular Monolith, using multiple DbContexts can be practical because you can configure a different database schema per DbContext, giving you logical separation at the database level.

Read Replicas
You can configure a separate DbContext instance to access the read replica of your database, and use that DbContext for read-only queries. You can also configure QueryTrackingBehavior.NoTracking on the DbContext level to improve query performance.

Creating Multiple DbContexts In a Single Application

Here's how you can easily configure multiple DbContexts. Let's say we have a CatalogDbContext and an OrderDbContext in our application. We want to configure them using the following constrainsts:

  • Both DbContexts use the same database
  • Each DbContext has a separate database schema
public class CatalogDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }

    public DbSet<Category> Categories { get; set; }
}

public class OrderDbContext : DbContext
{
    public DbSet<Order> Orders { get; set; }

    public DbSet<LineItem> LineItems { get; set; }
}

First we need to configure the CatalogDbContext and OrderDbContext with the DI container. You can do this by calling the AddDbContext method and specifying which DbContext is being configured, and then using the SQL provider specific method to pass the connection string. In this case I'm connecting to SQL Server with the UseSqlServer method.

using Microsoft.EntityFrameworkCore;

services.AddDbContext<CatalogDbContext>(options =>
    options.UseSqlServer("CONNECTION_STRING"));

services.AddDbContext<OrderDbContext>(options =>
    options.UseSqlServer("CONNECTION_STRING"));

If you just want to use both DbContexts in the same schema, then this is all the configuration you need. You can now inject the DbContext instances in your application and use them.

However, if you want to configure a different schema for each DbContext then you also need to override the OnModelCreating method and specify the custom schema with HasDefaultSchema.

public class CatalogDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }

    public DbSet<Category> Categories { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("catalog");
    }
}

public class OrderDbContext : DbContext
{
    public DbSet<Order> Orders { get; set; }

    public DbSet<LineItem> LineItems { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("order");
    }
}

Limitations with multiple DbContexts:

  1. It's not possible to do a join between different DbContext instances, because EF Core doesn't know if they are using the same database
  2. Transactions will only work if the DbContexts are using the same database. You have to create a new transaction and share it between the DbContexts by calling the UseTransaction method

Migrations History Table

If you decide to use different schemas per DbContext, you will be unpleasantly surprised to learn that the default schema doesn't apply to the migrations history table.

You need to configure this by calling the MigrationsHistoryTable method and specifying the table name and schema where the migrations history for that context will live. I used the HistoryRepository.DefaultTableName constant in this example, but you can specify a custom table name if you want to.

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;

services.AddDbContext<CatalogDbContext>(options =>
    options.UseSqlServer(
        "CONNECTION_STRING",
        o => o.MigrationsHistoryTable(
            tableName: HistoryRepository.DefaultTableName,
            schema: "catalog")));

services.AddDbContext<OrderDbContext>(options =>
    options.UseSqlServer(
        "CONNECTION_STRING",
        o => o.MigrationsHistoryTable(
            tableName: HistoryRepository.DefaultTableName,
            schema: "order")));

Benefits Of Using Multiple DbContexts

Using multiple DbContexts can offer several benefits to your application:

  • Separation of concerns
  • Better performance
  • More control & security

Each DbContext can be responsible for a specific subset of the application's data, which can help organize the code and make it more modular.

When you separate data access into multiple DbContexts, the application can reduce the risk of contention and improve concurrency, and this can improve performance.

And if you're using multiple DbContexts, you can configure more granular access control to improve application security. You can also optimize performance and resource usage.

In Summary

Using multiple EF Core DbContexts in a single application is straightforward and has many benefits.

For ready-heavy applications you can configure a separate DbContext to turn off query tracking by default and get improved performance.

Also, using multiple DbContexts is practical if you're building a Modular monolith. You can configure the DbContexts to be in separate database schemas, giving you logical separation at the database level.

That's all for today.

See you next week.


Whenever you're ready, there are 4 ways I can help you:

  1. Modular Monolith Architecture (COMING SOON): This in-depth course will transform the way you build monolith systems. You will learn the best practices for applying the Modular Monolith architecture in a real-world scenario. Join the waitlist here.
  2. Pragmatic Clean Architecture: This comprehensive course will teach you the system I use to ship production-ready applications using Clean Architecture. Learn how to apply the best practices of modern software architecture. Join 2,600+ students here.
  3. Patreon Community: Join a community of 1,050+ engineers and gain access to the source code I use in my YouTube videos, early access to future videos, and exclusive discounts for my courses. Join 1,050+ engineers here.
  4. Promote yourself to 46,000+ subscribers by sponsoring this newsletter.

Become a Better .NET Software Engineer

Join 46,000+ engineers who are improving their skills every Saturday morning.