簡體   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