2017-09-14 80 views
0

不幸的是Entity Framwork Core不再支持IDatabaseInitializer s:所以没有DropCreateDatabaseAlways.Seed()DropCreateDatabaseIfModelChanges.Seed()。 :-(建立自动迁移和播种而不损坏实体框架工具链

所以人们在那里写了很多东西:。

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

我在Startup.Configure 0结束想出了以下行在那里我得到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末败坏了实体框架工具链:

PM> Add-Migration MyMigration 
PM> Update-Datebase 

还有:

PM> Update-Datebase NameOfPreviousMigration 
PM> Remove-Migration 

那些命令行程序正在使用方法Program.BuildWebHost()致电我的StartupStartup.ConfigureServices()以及Startup.Configure()(即使不需要:https://github.com/aspnet/EntityFrameworkCore/issues/9076)。即使我打电话Remove-Migration狗屎糟糕的打扇:Remove-MigrationStartup.Configure()→迁移&种子(数据库是在最新的迁移=无迁移删除)→错误:

The migration '20170914084432_MyMigration' has already been applied to the database. Revert it and try again. If the migration has been applied to other databases, consider reverting its changes using a new migration.

简单的说,我怎么能运行我的移植&种子从工具链分别告诉我的工具链手Startup.Configure()


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

回答

0

经过数小时的猜测和失败,我放弃了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作为服务。目前没有办法指向另一个班级!如果你尝试,你会得到:

      Scaffolding failed to edit Startup class to register the new Context using Dependency Injection. Make sure there is a Startup class and a ConfigureServices method and Configuration property in it.

    • 除了脚手架也调用BuildWebHost方法。所以你也需要在这里使用Startup。否则,你得到这个消息误导:

      No parameterless constructor defined for this object.

  • 迁移仅使用BuildWebHost方法去启动类(同脚手架)。

结论:

所以,如果你不想打电话给你的迁移和播种每次你添加一个新的控制器或添加/删除迁移,你必须提供一个瘦Startup类,并把(运行时)的东西在别的地方!

您可以在设计时和运行时创建时创建一个基类,重用ConfigureServices()方法。 (请记住脚手架在修改基本类型Startup时总是会失败,但据我所知,它只会通过注册MyDbContext作为服务而发生,而且应该可以管理。)