I have a web application which is supposed to be composed as a series of plugins into a core infrastructure. A plugin is a compiled CLR dll + some content files which will be put in a certain location. I'm using Autofac to scan and register types out of the assembly, and some fancy routing to serve controllers and assets from there. But, since each plugin assembly can contain a DbContext (by convention each will use its own database), I can't quite figure out what to do there.
Now I've found a lot of stuff around how to use multiple contexts but it all requires knowing what these will be at development time. My application does not know what contexts will be used until runtime.
What I'm looking for ideally is would like is some way to do
ApplyMigrations<MyDbContext, MyDbConfiguration>();
Though I would also somehow have to provide an ordered set of migrations to apply (if using explicit migrations).
Where I'm stumbling currently is the standard
Database.SetInitializer(...)
since it is a static singleton and each dbcontext in my system has its own initializer.
First, of all SetInitializer
stores the IDatabaseInitializer
objects in a dictionary with the context Type as key, so theoretically multiple calls of SetInitializer
should work fine.
On the other hand, if that doesn't work, another option is to explicitly perform initialization:
class YourContext : DbContext
{
static YourContext()
{
Database.SetInitializer<YourContext>(YourMigratingDatabaseInitializer);
using (var context = new YourContext())
{
context.Database.Initialize(false);
}
}
public YourContext()
{
Database.SetInitializer<YourContext>(null);
}
}
Perhaps write an interface for bootstrapping a plugin, so IPluginBootstrapper - from here you could pass in a ContainerBuilder to add to a collection of services that the plugin provides, or return a built Container that the plugin builds and combine it on the host. In this way, you're pushing the responsibility of the all the DB seed/migration work into each plugin - so when you drop in a new dll, when it's bootstrapped it can run it's own upgrade path.
Another alternative, perhaps you can have a configuration section which defines a pair of types, so Tuple and tell Autofac to find all pairs of these in the plugins directory, and then call SetInitializer with what is resolved?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With