从多个不同的 Nuget 包运行 EF Core 迁移?

问题描述 投票:0回答:1

我正在创建一个主要围绕插件构建的项目。每个插件最终都会是一个 Nuget 包,但目前它们是引用的项目。

在每个插件中,我希望用户能够创建自己的实体和迁移(如果插件需要)。我已经在启动时找到了每个插件的程序集,我只需要一种运行迁移的方法。

我已经看到可以选择传递另一个程序集的名称来进行迁移,就像这样

services
    .AddDbContext<MyDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection"),
            x => x.MigrationsAssembly("NameOfAssemblyContainingMigrations")));

但是,这行不通,因为主项目也有迁移,我希望允许多个插件添加迁移,而不仅仅是一个。

这肯定是以前问过的问题吗?

entity-framework entity-framework-core entity-framework-migrations
1个回答
0
投票

我认为你应该重新考虑为他们运行迁移。

大多数环境,尤其是企业,不希望迁移自动运行,他们希望迁移在部署上运行,因此您的应用程序不需要专门了解迁移。

我们为我们的“服务库”解决类似问题所做的是一个多部分的答案。我们需要一种方法来拥有一个独立的 DbContext(因此不需要像您所做的那样进行扩展)。我们通过这样做解决了这个问题:

  1. 在每个 nuget 包中,让带有数据库上下文的“数据”项目在其中包含迁移。
  2. 每个包都会在使用应用程序的数据项目中被引用。
  3. 为每个服务项目添加“DesignTime”
    IDesignTimeDbContext
    实现(我们在一个文件中完成此操作)。不知道为什么需要这样做,但它对我们有用
  4. 构建运行一个 json 文件,这是运行命令所需的“ContextNames”数组
    dotnet ef script -Idempotent -Context {insertContextname}
  5. 获取该脚本输出并将其组合成一个脚本,然后将其放入工件中以便稍后运行。

要回答您的具体问题,或者如果您执意要为它们运行迁移,我仍然会将迁移创建本身留给使用应用程序。使用泛型时不需要指定迁移程序集。

services.AddDbContext<TDbContext>(options=> options.UseSqlServer(...));

您可能必须使用泛型。您的每个项目都应该需要一个公开的方法来告诉您 dbcontext 类型是什么。 您的项目必须为消费者调用此名称。

services.AddMyProject<MyDbContext>()
,在您的
app.UseMyproject<MyDbContext>()
方法中,您只需创建一个新范围(下面是使用通用类型的方法):

using (var scope = appBuilder.ApplicationServices.CreateScope())
{
    var db = scope.ServiceProvider.GetService<TDbContext>();
    db.Database.Migrate();
}

在我们的这些服务项目中,我们在

IServiceCollection
IApplicationBuilder
上创建了扩展方法。

public static IServiceCollection AddXYZService<TDbContext>(this IServiceCollection services, XYZServiceConfiguration<TDbContext> configuration)
where TDbContext : XYZServiceDbContext
{ ...
 //your logic here
 services.AddDbContext<TDbContext>(options=> options.UseSqlServer(...));
}

和应用程序构建器

public static IApplicationBuilder UseXYZService<TDbContext>(this IApplicationBuilder appBuilder) 
where TDbContext : XYZDbContext
{
    //your logic if needed, plus the migration using the migrations they made.  If you end up doing the script route, you don't need this at all.
    using (var scope = appBuilder.ApplicationServices.CreateScope())
    {
        var db = scope.ServiceProvider.GetService<TDbContext>();
        db.Database.Migrate();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.