Reputation: 667
I have a mulitenant application, which has multiple databases for different customers having same db structure.
In application, after user logs in based on his customer-id I will know connection string for his customer database and after his login button click event I will need to change my db context dynamically on the fly.
I am using EF 5.0 and Autofac IOC container. I have pasted my code here which is not helping me.
Whats the best way I can manage this?
string EntityFrameworkConnectionString = null;
var builder = new ContainerBuilder();
builder.Register(c =>
{
if (string.IsNullOrEmpty(EntityFrameworkConnectionString))
{
var profileProvider = c.Resolve<IConfigurationProfileProvider<CustomerProfile>>();
var profile = profileProvider.GetProfile();
EntityFrameworkConnectionString = profile.CustomerDatabaseConnectionString;
}
return new CustomerDataContext(EntityFrameworkConnectionString);
})
.As<ICustomerDataContext>()
.As<IDbContext>()
.InstancePerDependency();
builder.RegisterType<CustomerDataContextFactory>().As<ICustomerDataContextFactory>();
var assembly = Assembly.GetExecutingAssembly();
builder.RegisterAssemblyTypes(assembly)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces()
.InstancePerDependency();
Upvotes: 0
Views: 501
Reputation: 7436
I would do that like this:
Introduce an interface that will manage the connection strings:
public interface IConnectionStringManager
{
string GetConnectionString();
}
With the implementation that has IConfigurationProfileProvider injected into it:
public class ConnectionStringManager : IConnectionStringManager
{
private readonly IConfigurationProfileProvider<CustomerProfile> _configurationProfileProvider;
public ConnectionStringManager(IConfigurationProfileProvider<CustomerProfile> configurationProfileProvider)
{
_configurationProfileProvider = configurationProfileProvider;
}
public string GetConnectionString()
{
return _configurationProfileProvider.GetProfile().CustomerDatabaseConnectionString;
}
}
Then inject IConnectionStringManager into CustomerDataContext and get the connection string.
public CustomerDataContext(IConnectionStringManager connectionStringManager)
{
var connectionString = connectionStringManager.GetConnectionString();
// pass the connectionString to your context
}
And register ConnectionStringManager and CustomerDataContext as usual:
builder.RegisterType<ConnectionStringManager>().As<IConnectionStringManager>();
builder.RegisterType<CustomerDataContext>()
.As<ICustomerDataContext>()
.As<IDbContext>()
.InstancePerDependency();
BTW, Take a look at the Autofac Multitenant Integration which could ease multitenant support.
Upvotes: 1
Reputation: 16137
I don't really think you would need to use your IOC for this case (especially considering how complicated you've made it). Why not just store that connection string as a static variable, and then override your DbContext
's constructor to always use that variable?
Like so:
For the connection string:
public static class StaticVariables
{
public static string ConnectionString { get; set; }
}
For your DbContext
constructor:
public DbContext()
{
this(StaticVariables.ConnectionString);
}
Upvotes: 0