1

I need to be able create a DBContext with a specific DB connection string depending on the logged in user.

Users login via a JWT token at which point the application makes a call to a 3rd party to determine which database they should be connected to.

I am currently registering my ApplicationDBContext at startup:

services.AddDbContextFactory<ApplicationDBContext>(options => options.UseSqlServer(
                    Configuration.GetConnectionString("TestDbConString"),
                    h => h.UseHierarchyId()
                ));

I also have this service:

services.
...
.onAuthenticated(async c => {

    await getConnectionData(); // Returns the connection string. This can take a few seconds the first time subsequently it returns cached data.

})

Obviously I need to change things up a bit. How would you go about registering ApplicationDBContext with the correct/custom connection string?

UPDATE:

Here is my poor attempt at setting up a DbContextFactory.

using Microsoft.EntityFrameworkCore;
using MyApp.Models;

namespace MyApp.Data
{

    public class ApplicationDbContextFactory : IDbContextFactory<AppDbContext>
    {


        public ApplicationDbContextFactory test(){
            return new ApplicationDbContextFactory();
        }

        public AppDbContext CreateDbContext()
        {

            string ConnectionString = "";


            //Magic here to get my ConnectionString.

            DbContextOptionsBuilder<AppDbContext> options = new DbContextOptionsBuilder<AppDbContext>();
            options.UseSqlServer(
                ConnectionString,
                h => h.UseHierarchyId()
            );

            return new AppDbContext(options.Options);
        }
    }
}

Startup,cs

                services.AddTransient<ApplicationDbContextFactory>();
                services.AddTransient(provider => provider.GetService<ApplicationDbContextFactory>()!.CreateDbContext());

I am now getting an error:

Unexpected Execution Error : No service for type 'Microsoft.EntityFrameworkCore.IDbContextFactory`1[MyApp.Data.AppDbContext]' has been registered.

Update #2 This fixed it:

Startup.cs

services.AddTransient<IDbContextFactory<AppDbContext>, ApplicationDbContextFactory>();

Timothy Martens
  • 678
  • 4
  • 17
  • 1
    You need to create your own implementation of the DBContextFactory which will initialise a context based on the connection string which could come from anywhere. [This](https://stackoverflow.com/questions/36816215/dynamically-change-connection-string-in-asp-net-core) might help. – AliK Jun 30 '21 at 21:46
  • DBContextFactory doesn't accept any parameters to specify which tenant you'll be creating that dbcontext for, though, you're better off creating your own factory. – abdusco Jun 30 '21 at 21:49
  • Oh I thought you meant like `IDbContextFactory`, https://learn.microsoft.com/en-us/ef/core/dbcontext-configuration/#using-a-dbcontext-factory-eg-for-blazor. – abdusco Jun 30 '21 at 21:52
  • EFCore 5 can change the connStr on an existing context; are you using EFC5? – Caius Jard Jul 01 '21 at 06:17
  • https://blog.jeremylikness.com/blog/multitenancy-with-ef-core-in-blazor-server-apps/. Although the post is written for Blazor server, it still applies to DbContext. – abdusco Jul 01 '21 at 06:46
  • @AliK I believe that sounds like the best option. – Timothy Martens Jul 01 '21 at 20:22
  • 1
    `services.AddTransientApplicationDbContextFactory>();`? – Guru Stron Jul 01 '21 at 20:23

0 Answers0