EF Core 2.0 Add-Migraion 出現無法建立 DbContext 錯誤

傳統的設定再執行 Add-Migration 會出現錯誤:

PM> Add-Migration InitialCreation

Unable to create an object of type ‘OrderContext’. Add an implementation of ‘IDesignTimeDbContextFactory<OrderContext>’ to the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time.

這是因為 EF Core 2.0 有改變 Tools 的作法,在 Asp.net core 最佳的解法是:

WebHost.CreateDefaultBuilder(args)

如果是 Console program,可以用 emtpy constructor 的方式:

public class OrderContext : DbContext
{
    public OrderContext() { }
    public OrderContext(DbContextOptions<OrderContext> options) : base(options) { }
    public DbSet<OrderProcess> OrderProcesses { get; set; }
 
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"Server=(localdb)\MSSQLLocalDB;Database=Msmtest;Trusted_Connection=True;");
    }
}

重點在於 OnConfiguring 加上指定的 SqlServer connection。一旦產生 Migration 之後,就可以將 empty constructor comment 掉(因為可能會影響程式的正常邏輯)。

如果有多個 Context,可以在 Add-migration & Update-Database 中指定哪一個要進行更新:

Add-Migration Initial -Context LhcPlatformContext

Update-Database -Context LhcPlatformContext

請注意,如果使用 Seeding the Database 進行資料庫 seeding,那要注意必須要先拿掉 seed data 段落之後才會正確執行,否則會出現: “An error occurred while calling method ‘BuildWebHost’ on class ‘Program’. Continuing without the application service provider.

這個原因是因為我們都是使用 Development 環境在執行,因此會進入到 Seed() 函數,但在 Add-migration 時候實際上並沒有對應的資料庫表格,因此在執行 Seed() 會造成錯誤。

解學方案就是透過檢查 Migration 是否都已經執行後,在進行 Seed,。詳細作法參閱:How to seed your EF Core database

重點在於檢查是否都已經執行 migration:

using (var scope = app.ApplicationServices.CreateScope())
{
    var services = scope.ServiceProvider;
    if (!services.GetService<LhcPlatformContext>().AllMigrationsApplied())
    {
        var context = services.GetRequiredService<LhcPlatformContext>();
        context.Database.Migrate();
        LhcSeedData.Initializer(context);
    }
}

其中 AllMigrationsApplied() 如下:

public static bool AllMigrationsApplied(this DbContext context)
{
    var applied = context.GetService<IHistoryRepository>()
        .GetAppliedMigrations()
        .Select(m => m.MigrationId);
 
    var total = context.GetService<IMigrationsAssembly>()
        .Migrations
        .Select(m => m.Key);
 
    return !total.Except(applied).Any();
}

 

 

解決 EF Core 2.0 當呼叫 Add-Migraion 會出現無法產生的錯誤

EF Core 2.0 執行 Add-Migration 會出現錯誤:

  PM> Add-Migration InitialCreation
Unable to create an object of type 'OrderContext'. Add an implementation of 'IDesignTimeDbContextFactory<OrderContext>' to the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time.

這是因為 EF Core 2.0 有改變 Tools 的作法,在 Asp.net
core
最佳的解法是:

WebHost.CreateDefaultBuilder(args)

如果是 Console program,可以用 emtpy constructor 的方式:

public class OrderContext : DbContext
{
    public OrderContext() { }
    public OrderContext(DbContextOptions<OrderContext> options) : base(options) { }
    public DbSet<OrderProcess> OrderProcesses { get; set; }
 
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"Server=(localdb)\MSSQLLocalDB;Database=Msmtest;Trusted_Connection=True;");
    }
}

重點在於 OnConfiguring 加上指定的 SqlServer connection。一旦產生 Migration 之後,就可以將
empty constructor comment
掉(因為可能會影響程式的正常邏輯)。