2013-03-28 7 views
10

私はEntity Framework Code First Migrationを使用しており、統合テストスイートを実行するシナリオがあります。EF 5、コードファースト - 新しいデータベースを作成し、プログラムですべてのマイグレーションを実行

  1. ドロップ既存のテストデータベース(もしあれば)
  2. は、新しいテストを作成します。テストを実行するたびに、私は

    手順があるべきデータベースを再作成し、すべてのマイグレーションを適用したいですデータベース、そしてこれは私がに移行を追加した、と私は有効-移行は「InitialCreate」移行番目を作成するためのコマンドを使用既存のプロジェクトであるすべてのマイグレーション

  3. シードデータ

を適用で私のデータベースにすべてのテーブルを追加するコードが含まれています。

私のカスタムIDatabaseInitializerのコードは次のとおりです。私のInitialCreate移行のUp方法は、私が期待したものではありませんこれは、このコードによって呼び出さ取得されていない

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(); 
} 

。代わりに、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); 
} 
です
関連する問題