資料植入

資料植入是使用初始資料集來填入資料庫的程式。

EF Core 有數種方式可以達成此目的:

  • 模型種子資料
  • 手動移轉自訂
  • 自訂初始化邏輯

模型種子資料

不同于 EF6,在 EF Core 中,植入資料可以與實體類型產生關聯,做為模型組態的一部分。 然後 EF Core 移轉 可以自動計算將資料庫升級至新版本模型時,需要套用哪些插入、更新或刪除作業。

注意

移轉只會在判斷應該執行的作業以將種子資料放入所需狀態時,才會考慮模型變更。 因此,對移轉外部執行的資料所做的任何變更可能會遺失或造成錯誤。

例如,這會在 中設定 BlogOnModelCreating 種子資料:

modelBuilder.Entity<Blog>().HasData(new Blog { BlogId = 1, Url = "http://sample.com" });

若要新增具有關聯性的實體,必須指定外鍵值:

modelBuilder.Entity<Post>().HasData(
    new Post { BlogId = 1, PostId = 1, Title = "First post", Content = "Test 1" });

如果實體類型具有陰影狀態的任何屬性,匿名類別就可以用來提供值:

modelBuilder.Entity<Post>().HasData(
    new { BlogId = 1, PostId = 2, Title = "Second post", Content = "Test 2" });

擁有的實體類型可以以類似的方式植入:

modelBuilder.Entity<Post>().OwnsOne(p => p.AuthorName).HasData(
    new { PostId = 1, First = "Andriy", Last = "Svyryd" },
    new { PostId = 2, First = "Diego", Last = "Vega" });

如需更多內容, 請參閱完整的範例專案

將資料新增至模型之後, 應該使用移 轉來套用變更。

提示

如果您需要將移轉套用為自動化部署的一部分,您可以 建立可在執行前預覽的 SQL 腳本

或者,您可以使用 context.Database.EnsureCreated() 來建立包含種子資料的新資料庫,例如測試資料庫,或使用記憶體內部提供者或任何非關係資料庫時。 請注意,如果資料庫已經存在, EnsureCreated() 就不會更新資料庫中的架構或植入資料。 如果您打算使用移轉,就不應該呼叫 EnsureCreated() 關係資料庫。

模型種子資料的限制

這種類型的種子資料是由移轉所管理,而且腳本會更新資料庫中已存在的資料,而不需要連線到資料庫。 這會施加一些限制:

  • 即使通常由資料庫產生主鍵值,也必須指定主鍵值。 其將用來偵測移轉之間的資料變更。
  • 如果以任何方式變更主鍵,則會移除先前植入的資料。

因此,這項功能最適用于預期不會在移轉之外變更的靜態資料,且不相依于資料庫中的任何其他專案,例如郵遞區號。

如果您的案例包含下列任一項,建議您使用上一節所述的自訂初始化邏輯:

  • 用於測試的暫存資料
  • 相依于資料庫狀態的資料
  • 大型資料(植入資料會在移轉快照集中擷取,而大型資料可以快速導致大量檔案和效能降低)。
  • 需要資料庫產生索引鍵值的資料,包括使用替代索引鍵作為身分識別的實體
  • 需要自訂轉換的資料(不是由 值轉換 處理),例如某些密碼雜湊
  • 需要呼叫外部 API 的資料,例如 ASP.NET 核心身分識別角色和使用者建立

手動移轉自訂

將移轉新增至指定 HasData 之資料的變更會轉換成對 、 UpdateData()DeleteData()InsertData() 呼叫。 解決某些限制 HasData 的其中一種方法是手動將這些呼叫或 自訂作業 新增至移轉。

migrationBuilder.InsertData(
    table: "Blogs",
    columns: new[] { "Url" },
    values: new object[] { "http://generated.com" });

自訂初始化邏輯

執行資料植入的簡單且強大方式,是在主要應用程式邏輯開始執行之前使用 DbContext.SaveChanges()

using (var context = new DataSeedingContext())
{
    context.Database.EnsureCreated();

    var testBlog = context.Blogs.FirstOrDefault(b => b.Url == "http://test.com");
    if (testBlog == null)
    {
        context.Blogs.Add(new Blog { Url = "http://test.com" });
    }

    context.SaveChanges();
}

警告

植入程式碼不應該是一般應用程式執行的一部分,因為當多個實例執行時,這可能會導致並行問題,而且也需要應用程式具有修改資料庫架構的許可權。

根據部署的條件約束,初始化程式碼可以透過不同的方式執行:

  • 在本機執行初始化應用程式
  • 使用主要應用程式部署初始化應用程式、叫用初始化常式,以及停用或移除初始化應用程式。

這通常可以使用發行設定檔 來自動化