具有插件式系统的EF多上下文。如何在运行时应用迁移?

时间:2015-05-22 13:06:48

标签: c# entity-framework ef-migrations

我有一个Web应用程序,它应该被组成一系列插件到核心基础结构中。插件是一个已编译的CLR dll +一些内容文件,它们将放在某个位置。我正在使用Autofac来扫描和注册程序集中的类型,以及一些花哨的路由来从那里为控制器和资产提供服务。但是,由于每个插件程序集都可以包含一个DbContext(按照惯例,每个都将使用自己的数据库),我无法弄清楚该做什么。

现在我发现了很多关于如何使用多个上下文的内容,但这一切都需要知道这些在开发时的内容。我的应用程序不知道在运行时之前将使用哪些上下文。

理想情况下我想要的是某种方式

ApplyMigrations<MyDbContext, MyDbConfiguration>();

虽然我也不得不提供一组有序的迁移来应用(如果使用显式迁移)。

我目前磕磕绊绊的是标准

Database.SetInitializer(...)

因为它是一个静态单例,我系统中的每个dbcontext都有自己的初始化器。

2 个答案:

答案 0 :(得分:1)

也许编写一个用于引导插件的接口,所以IPluginBootstrapper - 从这里你可以传入一个ContainerBuilder来添加到插件提供的服务集合,或者返回一个构建的Container,该插件构建并将其组合在主机上。通过这种方式,您可以将所有数据库种子/迁移工作的责任推送到每个插件中 - 所以当您使用新的dll时,当它被引导时,它可以运行它自己的升级路径。

另一种选择,也许你可以有一个定义一对类型的配置部分,所以Tuple告诉Autofac在plugins目录中找到所有这些对,然后用解决的东西调用SetInitializer?

答案 1 :(得分:1)

首先,所有SetInitializerIDatabaseInitializer个对象存储在字典中,并将上下文Type作为键,因此理论上多次调用SetInitializer应该可以正常工作。

另一方面,如果这不起作用,另一个选择是显式执行初始化:

class YourContext : DbContext
{
    static YourContext()
    {
        Database.SetInitializer<YourContext>(YourMigratingDatabaseInitializer);
        using (var context = new YourContext())
        {
            context.Database.Initialize(false);
        }
    }

    public YourContext()
    {
        Database.SetInitializer<YourContext>(null);
    }
}