Reputation: 41
I am working on multi layered architecture with supporting multiple database per tenant in MVC. I need to create DBContext depending on the user logged in into data layer. How should I create generic DBContext and set connection string according to user?
Following is code to get connection string from Host Databsae and set it to Client Database. (In data/repository layer)
private static string GetConnectionString()
{
int tenantId;
HostDBContext hostContext = new HostDBContext();
//Get Tenant and set ID to get required connection string
tenantId = 1; //Get Tenant Id from session
var tenantDetails = hostContext.TenantDetails.Find(tenantId);
if (tenantDetails != null)
{
return tenantDetails.connectionstring;
}
return "default connection string";
}
Upvotes: 0
Views: 1381
Reputation: 5878
You're on the right track, but it won't be a generic DbContext
, just one that with a connection string that's set at runtime. So instead of GetConnectionString, you want to create a DbContext
factory that requires the tenant Id to return your new DbContext("connectionString").
Let's call it TenantDbContext
:
public class TenantDbContext : DbContext
{
public TenantDbContext(string connectionString) : base(connectionString)
{
}
// Or
public TenantDbContext(int tenantId) : base(GetConnectionString(tenantId))
{
}
}
if using a factory:
public class TenantDbContextFactory : IDbContextFactory<TenantDbContext, int>
{
public TenantDbContext Create(int tenantId)
{
var connectionString = GetConnectionString(tenantId);
return new TenantDbContext(connectionString);
}
// ... rest of factory
}
public interface IDbContextFactory<TContext, TKey> where TContext :DbContext
{
TContext Create(TKey key);
}
If you're using a dependency injection container, you can also wire it up to return the TenantDbContext
based on the tenant Id.
Upvotes: 1