rajcool111
rajcool111

Reputation: 667

EF Switch between different contexts of same type

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

Answers (2)

Alexandr Nikitin
Alexandr Nikitin

Reputation: 7436

I would do that like this:

  1. Introduce an interface that will manage the connection strings:

    public interface IConnectionStringManager
    {
        string GetConnectionString();
    }  
    
  2. 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;
        }
    }  
    
  3. Then inject IConnectionStringManager into CustomerDataContext and get the connection string.

    public CustomerDataContext(IConnectionStringManager connectionStringManager)
    {
        var connectionString = connectionStringManager.GetConnectionString();
        // pass the connectionString to your context
    }
    
  4. 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

Corey Adler
Corey Adler

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

Related Questions