我正在创建一个主要围绕插件构建的项目。每个插件最终都会是一个 Nuget 包,但目前它们是引用的项目。
在每个插件中,我希望用户能够创建自己的实体和迁移(如果插件需要)。我已经在启动时找到了每个插件的程序集,我只需要一种运行迁移的方法。
我已经看到可以选择传递另一个程序集的名称来进行迁移,就像这样
services
.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection"),
x => x.MigrationsAssembly("NameOfAssemblyContainingMigrations")));
但是,这行不通,因为主项目也有迁移,我希望允许多个插件添加迁移,而不仅仅是一个。
这肯定是以前问过的问题吗?
我认为你应该重新考虑为他们运行迁移。
大多数环境,尤其是企业,不希望迁移自动运行,他们希望迁移在部署上运行,因此您的应用程序不需要专门了解迁移。
我们为我们的“服务库”解决类似问题所做的是一个多部分的答案。我们需要一种方法来拥有一个独立的 DbContext(因此不需要像您所做的那样进行扩展)。我们通过这样做解决了这个问题:
IDesignTimeDbContext
实现(我们在一个文件中完成此操作)。不知道为什么需要这样做,但它对我们有用dotnet ef script -Idempotent -Context {insertContextname}
要回答您的具体问题,或者如果您执意要为它们运行迁移,我仍然会将迁移创建本身留给使用应用程序。使用泛型时不需要指定迁移程序集。
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();
}
}