C# EF多上下文与插件式系统。如何在运行时应用迁移?

C# EF多上下文与插件式系统。如何在运行时应用迁移?,c#,entity-framework,entity-framework-migrations,C#,Entity Framework,Entity Framework Migrations,我有一个web应用程序,它应该作为一系列插件组成一个核心基础设施。插件是一个编译的CLR dll+一些内容文件,这些文件将放在某个位置。我正在使用Autofac扫描和注册程序集中的类型,并使用一些奇特的路由为控制器和资源提供服务。但是,由于每个插件程序集都可以包含一个DbContext(按照惯例,每个插件程序集都将使用自己的数据库),所以我不太清楚在那里该做什么 现在我已经找到了很多关于如何使用多个上下文的东西,但这都需要知道在开发时这些内容是什么。我的应用程序直到运行时才知道将使用什么上下文

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

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

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

ApplyMigrations<MyDbContext, MyDbConfiguration>();

由于它是一个静态单例,并且我的系统中的每个dbcontext都有自己的初始值设定项。

也许可以编写一个用于引导插件的接口,因此IPluginBootstrapper-从这里您可以传入一个ContainerBuilder,以添加到插件提供的服务集合中,或者返回插件构建的已构建容器,并将其组合到主机上。这样,您就把所有DB种子/迁移工作的责任推到了每个插件上——所以当您插入一个新的dll时,当它启动时,它可以运行自己的升级路径


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

首先,在所有
SetInitializer
中,将
IDatabaseInitializer
对象存储在字典中,上下文类型为键,因此理论上多次调用
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);
    }
}
classyourcontext:DbContext
{
静态YourContext()
{
SetInitializer(YourMigratingDatabaseInitializer);
使用(var context=newyourcontext())
{
context.Database.Initialize(false);
}
}
公共上下文()
{
Database.SetInitializer(null);
}
}

您是否考虑过将每个插件加载到单独的应用程序域中?不管怎么说,这样做对你来说可能是有意义的,而且很可能会解决这个问题。@LukeMcGregor但这是一个web应用程序,IIS管理应用程序域,所以我该如何处理?我认为在web应用程序中创建应用程序域没有任何问题,我最近参与的一个项目有一个使用应用程序域的插件系统。我们在网络应用和服务中使用了它们,没有任何问题。我明白了,我从来没有产生过自己的appdomain,但这听起来很有希望。你不会碰巧有任何示例代码,是吗?@LukeMcGregor所以我一直在阅读它,我不太确定你的建议是什么-你推荐每个插件在自己的应用程序域中运行完整的asp.net上下文吗?在这种情况下,您如何知道将请求路由到何处?我们是说只将EF内容加载到一个单独的AppDomain中,在这种情况下,如何在它们之间进行通信?是否所有实体都必须继承自
MarshalByRef
?是的,这正是我正在做的,问题是当
数据库时如何准确触发迁移。SetInitializer
是静态的我认为jjj有它-我看不出调用数据库有任何问题。初始化期间从插件调用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);
    }
}