繁体   English   中英

建立自动迁移和种子,而不会破坏实体框架工具链

[英]Establish auto migration and seeding without spoiling Entity Framework toolchain

不幸的是实体Framwork核心不支持IDatabaseInitializer小号了:所以没有DropCreateDatabaseAlways.Seed()DropCreateDatabaseIfModelChanges.Seed() :-(

因此人们在那里写了很多东西来:

  1. 如果不存在,则创建数据库。
  2. 将数据库迁移到最新版本。
  3. 如果#1(因为数据库为空),则在DbContext的具体实例的帮助下应用种子数据。

Startup.Configure的末尾提出了以下几行内容我在其中注入了IApplicationBuilder appIHostingEnvironment env

using (var scope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
    using (var context = scope.ServiceProvider.GetService<MyDbContext>())
    {
        var hasPendingMigrations = context.Database.GetPendingMigrations().Any();
        if (hasPendingMigrations) {
            var needsSeeding = !context.Database.GetAppliedMigrations().Any(); // No migration yet (no database or it's empty).

            context.Database.Migrate(); // Create/update schema (creates database if necessary).

            if (needsSeeding) {
                Seed(context);
                if (env.IsDevelopment()) {
                    SeedWithDummyData(context);
                }
            }
        }
    }
}

但是将这些行放在Startup.Configure的末尾会破坏Entity Framework工具链:

PM> Add-Migration MyMigration
PM> Update-Datebase

以及:

PM> Update-Datebase NameOfPreviousMigration
PM> Remove-Migration

这些Commandlet正在使用Program.BuildWebHost()方法来调用我的StartupStartup.ConfigureServices()以及Startup.Configure() (即使不需要: https : //github.com/aspnet/EntityFrameworkCore/issues/ 9076 )。 如果我打电话给Remove-Migration更糟了: Remove-MigrationStartup.Configure() →迁移和种子(数据库处于最新迁移状态=无法删除迁移)→错误:

迁移“ 20170914084432_MyMigration”已应用于数据库。 还原它,然后再试一次。 如果已将迁移应用于其他数据库,请考虑使用新的迁移还原其更改。

简而言之,如何将Migrate&Seed东西从工具链中移出,分别告诉我Startup.Configure()的工具链手?


请记住:我不喜欢使用IDesignTimeDbContextFactory因为...

经过数小时的猜测和失败,我放弃了Startup课! 因此,我现在将RuntimeStartup用于运行时,并将几乎空的Startup用于所有设计时任务(支架和迁移):

public class Program
{
    public static void Main(string[] args)
    {
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<RuntimeStartup>()
            .Build()
            .Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();
}

为什么这么复杂?

  • 脚手架
    • 第一个脚手架(添加第一个控制器+视图+实体框架)始终读取Startup类以将MyDbContext注册为服务。 (当前)无法指向另一个课程! 如果尝试,您将获得:

      脚手架无法编辑启动类以使用依赖注入来注册新的上下文。 确保其中包含一个Startup类以及一个ConfigureServices方法和Configuration属性。

    • 除此之外,脚手架还调用BuildWebHost方法。 因此,您也需要在此处使用Startup 否则,您会收到以下误导性消息:

      没有为此对象定义无参数构造函数。

  • 迁移仅使用BuildWebHost方法来获取启动类(与脚手架相同)。

结论:

因此,如果您不想在每次添加新的Controller或添加/删除迁移时都调用迁移和播种,则必须提供一个精益的Startup类并将(运行时)内容放到其他地方!

由您决定在设计时和运行时启动时重用ConfigureServices()方法来创建基类。 (请记住,脚手架在修改Startup基本类型时总是会失败。但是据我所知,只有将MyDbContext注册为服务才会发生。这应该是可管理的。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM