[entity-framework] 如何使用Entity Framework CodeFirst使我的數據庫成為種子?


Answers

即使在Application_Start正確調用Database.SetInitializer ,也沒有調用My Seed方法...原因很簡單:如果您還沒有任何實際使用數據庫上下文的代碼,則可能根本不會調用初始化程序。

Question

數據庫已成功創建(與表一樣)但未加種。 我花了幾個小時閱讀了大量的文章但卻未能得到它。 有什麼建議麼?

另外,是否可以調用初始化程序而無需在客戶端中引用我的DatabaseContext?

我已經包含了我能想到的所有相關代碼。 如果有任何其他方面的幫助,請告訴我。

我試過的事情:

  1. 我刪除了我的連接字符串(因為它默認為sqlexpress,只是名稱已更改)
  2. 我將DropCreateDatabaseIfModelChanges更改為DropCreateDatabaseAlways,仍然相同。

編輯:非常奇怪的是它曾經工作過一次,但我不知道它是如何或為什麼再次破裂。 我假設連接字符串,但誰知道。

DatabaseInitializer.cs

public class DatabaseInitializer : DropCreateDatabaseIfModelChanges<DatabaseContext>
{
  protected override void Seed(DatabaseContext context)
  {
    // Seeding data here
    context.SaveChanges();
  }
}

DatabaseContext.cs

public class DatabaseContext : DbContext
{
  protected override void OnModelCreating(DbModelBuilder mb)
  {
    // Random mapping code
  }

  public DbSet<Entity1> Entities1 { get; set; }
  public DbSet<Entity2> Entities2 { get; set; }

}

Global.asax.cs - Application_Start()

protected void Application_Start()
{
  Database.SetInitializer<DatabaseContext>(new DatabaseInitializer());
  AreaRegistration.RegisterAllAreas();
  RegisterGlobalFilters(GlobalFilters.Filters);
  RegisterRoutes(RouteTable.Routes);
}

客戶端web.config

<connectionStrings>
  <add name="DatabaseContext" connectionString="data source=.\SQLEXPRESS;Database=Database;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
</connectionStrings>

為了記錄,我在這里分享我的解決方案。 無論如何,導航所有評論都會很痛苦。 最後,我將DatabaseInitializer和DatabaseContext放在不同的類中。 我不明白,雖然這些微小的變化修復了它,但現在它是。

DatabaseInitializer.cs

public class DatabaseInitializer : CreateDatabaseIfNotExists<DatabaseContext>
{
  protected override void Seed(DatabaseContext context)
  {
    // Seed code here
  }
}

DatabaseContext.cs

public class DatabaseContext : DbContext
{
  public DatabaseContext() : base("MyDatabase") { }

  protected override void OnModelCreating(DbModelBuilder mb)
  {
    // Code here
  }

  public DbSet<Entity> Entities { get; set; }
  // Other DbSets
}

Global.asax.cs - Application_Start()

protected void Application_Start()
{
  Database.SetInitializer(new DatabaseInitializer());
  AreaRegistration.RegisterAllAreas();
  RegisterGlobalFilters(GlobalFilters.Filters);
  RegisterRoutes(RouteTable.Routes);
}



精心確保您不會多次聲明您的上下文變量。 如果在播種後再次聲明它,則種子將被覆蓋。




更新以注意此答案不正確! 我的數據庫沒有被種子的原因仍然是一個謎(但不是缺少默認的基礎構造函數調用,如@JaredReisinger所述)

我很欣賞這個問題有點老了,但我最終在這裡,所以其他人可能。 這是我的值得:

即使我刪除了數據庫並使用DropDatabaseInitialiser再次啟動,我的數據庫也被創建得很好但沒有播種。

閱讀上面的代碼後,我注意到我的上下文構造函數就是這個

public MyApp_Context()
{
    // some code
}

而上面的例子對我的設置如下

public MyApp_Context() : base("name=MyApp_Context")
{
    // some code
}

是的,我沒有調用基礎對象的構造函數! 我不會期望除了播種之外的所有內容都可以在這種情況下工作,但這似乎是(可重複的)情況。

注意,我實際上不需要在基礎構造函數調用中提供上下文名稱; 我最初只是這樣寫的,因為我正在復制上面解決方案的格式。 所以我的代碼就是這個,並且種子在初始數據庫創建時起作用。

public MyApp_Context() : base()
{
    // some code
}



當我發現Code First Features時,這恰好發生在我身上。 當您第一次使用Code First生成數據庫而沒有任何初始化策略時,通常會發生這種情況。

如果您決定稍後通過實施基於DropCreateDatabaseIfModelChanges的策略,但不修改模型,則不會調用Seed方法,因為數據庫生成和您的策略將僅在您下次更改模型時應用。

如果您遇到這種情況,只需嘗試修改您的模型以測試此假設,我敢打賭,您的數據庫將被填充;)

我還沒有解決方案,除了使用總是生成數據庫的策略,但我真的不能把初始化策略放在你的DbContext中,因為這個類是goind用於你的生產環境,雖然初始化策略似乎主要用於流暢的開發環境。




您可以調用update-database以在Configuration類中手動運行種子方法。 這也需要enable-migrations

PM> update-database
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
No pending code-based migrations.
Running Seed method.
internal sealed class Configuration : DbMigrationsConfiguration<ProjectManager.Data.Database.ProjectDb>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(ProjectManager.Data.Database.ProjectDb context)
    {
        context.Status.AddOrUpdate(
            new Status() { Id = 1, Text = "New" },
            new Status() { Id = 2, Text = "Working" },
            new Status() { Id = 3, Text = "Completed" },
            new Status() { Id = 4, Text = "Skipped" }
        );
    }
}



我也很難調用Seed()。 我非常感謝上面提到的所有有用的建議,並且使用DropCreateDatabaseAlways運氣好運......但不是總是!!

最近,我在我的Repository的構造函數中添加了以下代碼行,效果很好:

    public CatalogRepository()
    {
        _formCatalog.FormDescriptors.GetType();

    }

觸發Seed()被調用就足夠了。 如果你已經嘗試了這個答案之上的所有內容並且仍然沒有運氣,請嘗試一下。 祝你好運這真是一次耗時的體驗。




Related