简体   繁体   中英

Changing ASP.NET Core 2.0 Identity Connection String in Controller

I am creating a web application works off of a multitenancy structure. As such, each user request will lock that user a specific tenant based on the hostname (with different databases per tenant.) I can set a general context's connection string, but I am at a loss right now on figuring out how to change the connection string for the ASP.NET Core 2.0 Identity objects.

I see that the default way that they have us doing it is setting the UseAuthentication() in StartUp.cs. And then when the controller is called, DI then sets the UserManager and SignInManager objects. I am assuming I need to create new UserManager and SignInManager objects within each controller constructor passing the specific connection string for that tenant (not using DI at all.)

Any thoughts on this?

Clarification:

My hope is to figure out if it is possible to change the database connection string for a passed identity object to a controller by dependency injection.

// Startup class of asp.net core 2
public void ConfigureServices(IServiceCollection services)
{
    services.AddMultitenancy<Tenant, TenantResolver>();

    string accountsConnection = configuration.GetConnectionString("AccountsConnectionString");

    services.AddScoped<LicenseManager>();
    services.AddScoped<AccountManager>();


    services.AddEntityFrameworkSqlServer()
        .AddDbContext<AccountsContext>(options =>
        {
            options.UseSqlServer(accountsConnection);
        })
        .AddDbContext<MasterDataContext>(options => options.UseSqlServer(masterdataConnection))
        .AddDbContext<DataContext>();

    services.AddMvc();
}

// Tenantresolver which get's the connectionstring from the claims. (seperate file/class)
// On authentication i create several claims with one claim with the connectionstring per user. 
// I use a seperate accounts database where all the tenants are saved which each of them has his own connectionstring
public class TenantResolver : MemoryCacheTenantResolver<Tenant>
{
    private readonly AccountsContext Context;

    public TenantResolver(AccountsContext context, IMemoryCache cache, ILoggerFactory logger)
        :base(cache, logger)
    {
        Context = context;
    }

    protected override string GetContextIdentifier(HttpContext context)
    {
        return context.User.Claims.Where(r => r.Type == ClaimTypes.AccountIdType).Select(s => s.Value).SingleOrDefault();
    }

    protected override IEnumerable<string> GetTenantIdentifiers(TenantContext<Tenant> context)
    {
        return new[] { context.Tenant.Tenant_Id.ToString() };
    }

    protected override Task<TenantContext<Tenant>> ResolveAsync(HttpContext context)
    {
        TenantContext<Tenant> tenantContext = null;

        string claim = context.User.Claims.Where(r => r.Type == ClaimTypes.AccountIdType).Select(s => s.Value).SingleOrDefault();

        var tenant = Context.Accounts
                .Where(q => q.IsActive == true && q.Account_Id.ToString() == claim)
                .Select(s => new Tenant(s.Account_Id, s.DataStore.DatabaseConnection))
                .FirstOrDefault();

        if (tenant != null)
        {
            tenantContext = new TenantContext<Tenant>(tenant);
        }

        return Task.FromResult(tenantContext);
    }
}

// Tenant class where i save the info needed.
public class Tenant
{
    public Tenant(
        Guid tenant_id,
        string database_ConnectionString)
    {
        Tenant_Id = tenant_id;
        Database_ConnectionString = database_ConnectionString;
    }

    public Guid Tenant_Id { get; set; }
    public string Database_ConnectionString { get; set; }
}

// DbContext class which uses the tenant and links the connectionstring to the current tenant.
public class DataContext : DbContext
{
    private readonly Tenant Tenant;

    public DataContext(DbContextOptions<DataContext> options, Tenant tenant)
        : base(options)
    {
        this.Tenant = tenant;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (Tenant != null)
        {
            optionsBuilder.UseSqlServer(Tenant.Database_ConnectionString);
        }

        base.OnConfiguring(optionsBuilder);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM