Using Multiple Databases in ASP.NET Core via Entity Framework Core

In this article, we are going to learn how to add multiple databases in the ASP.NET Core project using Entity Framework Core.

We are going to show you how our repository pattern implementation helps us in the process by using abstractions that will hide all the implementation details from the presentation layer. 

Since we already have the repository pattern explained in our ASP.NET Core Repository Pattern article, we strongly suggest reading it first to learn more about the repository pattern implementation in ASP.NET Core Web API. We will modify the source code from that project and show you the benefits of the implementation of that pattern when adding multiple databases in an ASP.NET Core project. 

To download the source code for this article, you can visit our Multiple Databases repository.

Let’s start.

Using Multiple Databases to Support Migrations

If you open our project that you can download from our source code repository, you can execute initial migrations that will create the first database and populate the initial data:

PM> Update-Database -Context RepositoryContext

Now, let’s say we received a request for another external database that we have to use for the same project. Sometimes, that database would already contain the required data. But if we want to add some data to it, we need to enable migrations for that database as well.

To do that, we are going to start with the new model creation. So, let’s open the Entities project and then the Models folder, and add a new class:

public class Client
    public Guid Id { get; set; }
    public string Name { get; set; }

We’ll assume that our new database will hold information about external clients. Of course, we are going to use a simple model for this example.

Now, in the Entities/Configuration folder, we are going to populate our client table – once we execute a new migration:

public class ClientConfiguration : IEntityTypeConfiguration<Client>
    public void Configure(EntityTypeBuilder<Client> builder)
            new Client
                Id = new Guid("c1f33503-bb38-4fa1-98a0-6cfaf9986797"),
                Name = "External Client's Test Name"
If you are not sure why we use the IEntityTypeConfiguration interface, you can read our Migrations and Seed Data with Entity Framework Core article. There, you will find detailed explanations regarding migrations and seeding data.

Next, in the same project, we are going to add a new context class:

public class ExternalClientContext : DbContext
    public ExternalClientContext(DbContextOptions<ExternalClientContext> options)
    : base(options)

    protected override void OnModelCreating(ModelBuilder modelBuilder)
        modelBuilder.ApplyConfiguration(new ClientConfiguration());

    public DbSet<Client> Clients { get; set; }

If we use multiple contexts in our project, we have to provide the TContext parameter for the DbContextOptions class. In this case, the parameter is of ExternalClientContext type. But if you check the RepositoryContext class, you will see that the parameter is of RepositoryContext type.

Registering Contexts for Multiple Databases in ASP.NET Core

If we inspect the appconfig file from the main project, we are going to find multiple connection strings:

  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
  "ConnectionStrings": {
    "sqlConnection": "server=.; database=CompanyEmployeeDb1; Integrated Security=true",
    "externalClientConnection": "server=.; database=CompanyEmployeeDb2; Integrated Security=true"
  "AllowedHosts": "*"

After adding the connection string, we can register a new context in the ServiceExtensions class inside the Extensions folder:

public static void ConfigureExternalClientContext(this IServiceCollection services, IConfiguration configuration) =>
            services.AddDbContext<ExternalClientContext>(opts =>
                opts.UseSqlServer(configuration.GetConnectionString("externalClientConnection"), b => b.MigrationsAssembly("CompanyEmployees")));

Lastly, we have to call this method in the Starup class for .NET 5:


Or in .NET 6 in the Program class:


That’s it.

We can create a new migration:

PM> Add-Migration ExternalClientData -Context ExternalClientContext

And execute it:

Update-Database -Context ExternalClientContext

Once that’s done, we will have both databases created:

Injecting Multiple Databases in the Repository Pattern

After successful migrations for multiple databases, we can start using both databases in our repository pattern to fetch the data from them.

In the Repository Pattern article, we have used only the RepositoryContext class in our RepositoryBase class (Repository project) thus limiting our repository to a single database:

public abstract class RepositoryBase<T> : IRepositoryBase<T> where T : class
    protected RepositoryContext RepositoryContext;

    public RepositoryBase(RepositoryContext repositoryContext) => RepositoryContext = repositoryContext;

Now, we can modify that.

So, let’s inspect a new RepositoryBase implementation:

public abstract class RepositoryBase<TContext, T> : IRepositoryBase<T> where T : class where TContext : DbContext
    protected TContext _context;

    public RepositoryBase(TContext context) => _context = context;

This time, we are using RepositoryBase with two generic parameters. The first one is for the context class, and the second one is for the entity. Additionally, we are restricting our TContext parameter to be only of DbContext type.

To continue, let’s create a new interface in the Contracts project:

public interface IClientRepository
    IEnumerable<Client> GetAllClients(bool trackChanges);

And, let’s create a repository class in the Repository project, that implements this interface:

public class ClientRepository : RepositoryBase<ExternalClientContext, Client>, IClientRepository
    public ClientRepository(ExternalClientContext clientContext)

    public IEnumerable<Client> GetAllClients(bool trackChanges) => 

We can see that following the same pattern from the previous implementation, our class inherits from the RepositoryBase class and our new interface. But this time, our RepositoryBase class has two parameters.

Additionally, we can inspect another repository class that uses a different context class:

public class CompanyRepository : RepositoryBase<RepositoryContext, Company>, ICompanyRepository
    public CompanyRepository(RepositoryContext repositoryContext)
        : base(repositoryContext)

    public IEnumerable<Company> GetAllCompanies(bool trackChanges) =>
        .OrderBy(c => c.Name)

Here we use a different context class and of course a different entity.

Supporting Multiple Databases in RepositoryManager (UoW)

Now, we have to modify the IRepositoryManager interface to provide our presentation or service layer (if you have both) with the possibility to call new repository classes:

public interface IRepositoryManager
    ICompanyRepository Company { get; }
    IEmployeeRepository Employee { get; }

    IClientRepository Client { get; }

    void Save();

And we have to modify the RepositoryManager class:

public class RepositoryManager : IRepositoryManager
    private RepositoryContext _repositoryContext;
    private ExternalClientContext _externalClientContext;

    private ICompanyRepository _companyRepository;
    private IEmployeeRepository _employeeRepository;

    private IClientRepository _clientRepository;

    public RepositoryManager(RepositoryContext repositoryContext, ExternalClientContext externalClientContext)
        _repositoryContext = repositoryContext;
        _externalClientContext = externalClientContext;


    public IClientRepository Client
            if (_clientRepository is null)
                _clientRepository = new ClientRepository(_externalClientContext);

            return _clientRepository;

    public void Save() => _repositoryContext.SaveChanges();

Since we don’t have any modification methods in our project, we didn’t modify the Save method to include additional context. But you can always do that and use ChangeTracker.HasChanges() to determine which context has changed:

public void Save()
  if (_repositoryContext.ChangeTracker.HasChanges())

Or you can add just both contexts in the Save method and let EF Core do the check for you. It’s up to you.

From the architectural point of view, if you have to modify both databases at the same time and the data from both databases need to be in sync, then it is probably a better solution to use just a single database. But if your second database is not connected to the main one, and modifications are not related to each other, which should be the case most of the time, feel free to continue using multiple databases in the project.

Now we can use this in a controller or a service class – depends on your project. For the sake of simplicity, we’ll create another endpoint in the existing CompaniesController:

public class CompaniesController : ControllerBase
    private readonly IRepositoryManager _repository;
    private readonly ILoggerManager _logger;
    private readonly IMapper _mapper;

    public CompaniesController(IRepositoryManager repository, ILoggerManager logger, IMapper mapper)
        _repository = repository;
        _logger = logger;
        _mapper = mapper;

    public IActionResult GetCompanies()
        var companies = _repository.Company.GetAllCompanies(trackChanges: false);

        var companiesDto = _mapper.Map<IEnumerable<CompanyDto>>(companies);

        return Ok(companiesDto);

    public IActionResult GetTests()
        var tests = _repository.Client.GetAllClients(trackChanges: false);

        return Ok(tests);

You can see that we don’t have to modify anything in the presentation layer – we just add a new endpoint and use our repository manager as if nothing has changed in the repository implementation.

Testing Data Fetching From Multiple Databases in ASP.NET Core

To test this, we are going to start our application and send a Postman request for the first database:

Right after that request, we are going to send another one that uses the second database:

We can see that our project works with multiple databases without a single problem.


That’s it.

We’ve seen how to use multiple databases in ASP.NET Core with Entity Framework core. Additionally, we’ve shown the advantage of using our repository pattern implementation. We can hide all this logic inside the repository layer and keep using it in our presentation/service layers as if nothing has changed in the project.

Until the next article,

All the best.

Marinko Spasojevic

View Comments

  • In the RepositoryManager class(UOW), we will need to add another Save() Method for _externalClientContext.SaveChanges() for any Write operation?

    • You can do that in multiple ways. One of those is adding another SaveExternal method as you suggested.

      Another would be to just add _externalClientContext.SaveChanges(); to the Save method. EF Core checks whether the changes have been made in the current context and if there are no changes it will save nothing. So you can have both contexts with the SaveChanges method called inside the Save method.

      The third option is to use ChangeTracker.HasChanges(), something like this:

      public void Save()
        if (_repositoryContext.ChangeTracker.HasChanges())

      In this case, you are executing just that context that really has changes detected.

  • Hi Marinko,

    Thank you for the post. This helps a lot because this what I exactly looking for (:
    Once thing I wanted to know that, Is there a way to make those Generic DB context optional ?
    I mean can we make it like this that someone can pass their DB context from outside else it will take the default one.

    • Hello there. If you are talking about the Context class then I have to admit that I have never done that, so I am not sure is there a way to do so. But if you think about each repository class, then it is better to keep it like this since each repo class should work only with that specific entity. We already have a repository base that can accept any context.

      • Thank you for your response.
        But actually have a situation where I have my base Repository which except two thing (1) Entity and (2) Audit Entity. And I'm using Entity Framework Plus as Audit solution.
        That Repository solution works fine when i keep all the entity tables and audit tables in same database instance but for some reason i have to separate out the same in two database instance. In that case I end-up passing two DbContext.
        I'm not sure if it's correct??

  • I made replica on sql server, now i have master and slave database, i wont use master only write and slave for only read, do you have any article with helps me to implement it in repository pattern?

    • Well, we don't have anything that specific. But, since your repository user classes (in this article CompanyRepository and ClientRepository) communicate with DBs, just separate the logic. Ones that have an interaction with the master db shouldn't handle read operations and vice versa.

      • thank you, but when I read data from slave/readonly (for example table x and record with id 5) database and than for some reason I want to update this record, (update must happened in master) how can I handle this? I must read record again from master(table x with id 5) and than update?(probably no )

        • Well, without going too much into why you have this db structure, and why this is not just a single table, I must say that I don't understand why you have master and slave DBs where you just read data from one db and modify data in another db. When you do update, you have to read the data, assign changes, and then execute the modification in db, for me, it just doesn't make sense to have two DBs. That means, if you delete the data from the master table, you should do it in the child because both have the same data... This is just redundant. I never worked with such a db structure and to be honest, I have no idea what is the proper way of handling that.

Published by
Marinko Spasojevic

Recent Posts

Code Maze Weekly #133

Issue #133 of the Code Maze weekly. Check out what's new this week and enjoy…

Updated Date Aug 5, 2022

Type Checking and Type Casting in C#

In this article, we are going to learn various ways of converting a value from…

Updated Date Aug 5, 2022

Sort Dictionary by Value in .NET

In this article, we are going to learn how to sort the values in the…

Updated Date Aug 4, 2022

Blazor WebAssembly Exception Handling With Error Boundaries

In this article, we will look at how to handle unexpected errors in Blazor WebAssembly…

Updated Date Aug 3, 2022

LINQ Improvements in .NET

In this article, we will discuss the new LINQ improvements introduced in .NET 6.  We…

Updated Date Aug 2, 2022

Concatenate Lists in C#

In this article, we are going to cover six different ways to concatenate lists in…

Updated Date Aug 1, 2022