2013-03-28 22 views
10

我正在使用Entity Framework Code First遷移,並且我有一個場景,我想運行一組集成測試。每次運行測試,我想重新創建數據庫,並適用所有遷移EF 5,Code First - 創建一個新數據庫並以編程方式運行所有遷移

的步驟應該是:

  1. 除去現有的測試數據庫(如果有的話)
  2. 創建一個新的測試數據庫和應用所有遷移
  3. 種子數據

這是我添加遷移到現有的項目,我用啓用的遷移命令來創建一個「InitialCreate」移民日at包含將所有表添加到我的數據庫的代碼。

的代碼在我的自定義IDatabaseInitializer如下:

public void InitializeDatabase(MyContext context) 
{ 
    //delete any existing database, and re-create 
    context.Database.Delete(); 
    context.Database.Create();    

    //apply all migrations 
    var dbMigrator = new DbMigrator(new Configuration()); 
    dbMigrator.Update(); 

    //seed with data 
    this.Seed(context); 

    context.SaveChanges(); 
} 

我InitialCreate遷移的Up方法是沒有得到這個代碼調用,這是不是我的預期。相反,所有表格都是在調用Database.Create()方法時創建的。我需要InitialCreate遷移才能運行,因爲我有額外的代碼來創建存儲過程。

所以我的問題是,我如何以編程方式創建一個新的數據庫並運行所有遷移(包括InitialCreate遷移)?

回答

4

以下代碼使我能夠滿足問題中概述的集成測試場景的需求,但肯定還有更好的方法嗎?

public void InitializeDatabase(MyContext context) 
{ 
    //delete any existing database, and re-create 
    context.Database.Delete(); 

    var newDbConnString = context.Database.Connection.ConnectionString; 
    var connStringBuilder = new SqlConnectionStringBuilder(newDbConnString); 
    var newDbName = connStringBuilder.InitialCatalog; 

    connStringBuilder.InitialCatalog = "master"; 

    //create the new DB 
    using(var sqlConn = new SqlConnection(connStringBuilder.ToString())) 
    { 
     using (var createDbCmd = sqlConn.CreateCommand()) 
     { 
      createDbCmd.CommandText = "CREATE DATABASE " + newDbName; 
      sqlConn.Open(); 
      createDbCmd.ExecuteNonQuery(); 
     } 
    } 

    //wait up to 30s for the new DB to be fully created 
    //this takes about 4s on my desktop 
    var attempts = 0; 
    var dbOnline = false; 
    while (attempts < 30 && !dbOnline) 
    { 
     if (IsDatabaseOnline(newDbConnString)) 
     { 
      dbOnline = true; 
     } 
     else 
     { 
      attempts++; 
      Thread.Sleep(1000); 
     } 
    } 

    if (!dbOnline) 
     throw new ApplicationException(string.Format("Waited too long for the newly created database \"{0}\" to come online", newDbName)); 

    //apply all migrations 
    var dbMigrator = new DbMigrator(new Configuration()); 
    dbMigrator.Update(); 

    //seed with data 
    this.Seed(context); 

    context.SaveChanges(); 
} 

private bool IsDatabaseOnline(string connString) 
{ 
    try 
    { 
     using (var sqlConn = new SqlConnection(connString)) 
     { 
      sqlConn.Open(); 
      return sqlConn.State == ConnectionState.Open; 
     } 
    } 
    catch (SqlException) 
    { 
     return false; 
    } 
} 
1

只要刪除「創建數據庫」步驟並使用它們自己的遷移。我把一個樣本項目放在GitHub上,但重要的是

Configuration config = new Configuration(); 
DbMigrator migrator = new DbMigrator(config); 

foreach (string s in migrator.GetPendingMigrations()) 
{ 
    migrator.Update(s); 
}