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

EF multi-context with a plugin-style system. How to apply migrations at runtime?

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

现在我发现了很多关于如何使用多个上下文的内容,但这都需要在开发时知道这些内容。我的应用程序直到运行时才知道将使用什么上下文。

我理想中寻找的是某种方法

ApplyMigrations<MyDbContext, MyDbConfiguration>();

虽然我也必须以某种方式提供一组有序的迁移来应用(如果使用显式迁移)。

我目前遇到的问题是标准

Database.SetInitializer(...)

因为它是静态单例并且我系统中的每个 dbcontext 都有自己的初始化程序。

也许编写一个用于引导插件的接口,所以 IPluginBootstrapper - 从这里您可以传入一个 ContainerBuilder 以添加到插件提供的服务集合,或者 return 插件构建的构建容器并将其组合在主机上。通过这种方式,您将所有 DB seed/migration 工作的责任推给了每个插件 - 所以当您放入一个新的 dll 时,当它被引导时它可以 运行 它是自己的升级路径。

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

首先,SetInitializerIDatabaseInitializer 对象存储在以上下文类型为键的字典中,因此理论上 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);
    }
}