问题
I'm building a multi tenant (db per tenant) application.
- the application - .net MVC4
- the data layer entity framework code first repositories
- the repositories are injected into the application via structure map
The structuremap config:
var connectionString = ConfigurationManager.ConnectionStrings["AccessControlDB"].ToString();
ObjectFactory.Initialize(x =>
{
x.For<IAccessControlContext>().Use<AccessControlContext>().Ctor<string>("connectionString").Is(connectionString);
x.For<IGenericRepository<Identities>>().Use<GenericRepository<IAccessControlContext, Identities>>();
x.Scan(scan =>
{
scan.AssembliesFromApplicationBaseDirectory();
scan.ExcludeNamespace("StructureMap");
scan.WithDefaultConventions();
});
});
A new requirement for having each tenant isolated by database has come up, so having tenantIDs is no longer sufficient.
I've gotten as far as having a meta database to store the data required to construct the connection strings, but I'm at a loss on how to pass the connection string to the repository.
At first, I thought I could just expose the connection string as a property, but there is no way to change the connection string after the context has already been instantiated by structuremap.
回答1:
Instead of passing a connection string to the repositories, do the following:
- Inject an
IContextFactory
into the repositories. This context factory can create newDbContext
instances. - Inject an
ITenantProvider
into the connection factory.
Injecting a context factory into the repositories has the following advantages:
- Make it considerably easier to configure the container, because you remove the ambiguity that
string
values bring and this prevents you from having to inject that connection string into many classes. - It allows you to hide the complexity of resolving the connection string behind an abstraction, since the context factory is now responsible of creating the right connection string (based on the tenant information it got from the
ITenantProvider
implementation). - By returning new
DbContext
instances from the factory instead of returning connection strings, you hide the creation of theDbContext
. This makes your repository easier and makes it easier to change it later on.
Note that I'm just guessing here how your repository works so the use of an IContextFactory
might not be the best option. But by preventing to inject the connection string directly and hiding it behind an abstraction (that even does a bit more than just returning that connection string), you can make both your DI configuration and application code considerably easier and maintain and test.
来源:https://stackoverflow.com/questions/16843592/dynamic-connection-string-for-injected-repository