2013-03-28 9 views
10

Entity Framework Code İlk geçişleri kullanıyorum ve bir bütünleştirme testi takımı çalıştırmak istediğim bir senaryo var.EF 5, Kod İlk - Yeni bir veritabanı oluşturun ve tüm geçişleri programlı olarak çalıştırın

  1. Damla mevcut test veritabanı (varsa)
  2. yeni bir test oluşturun: testler her çalıştırdığınızda, ben

    adımlar olmalıdır veritabanını yeniden oluşturmak ve tüm göçler uygulamak istediğiniz veritabanı ve tüm taşıma işlemlerini

  3. Tohum verilerini

Bu benim için göçler ekledik varolan projeyi olduğunu uygulamak ve ben Enable-göçler bir "InitialCreate" göç inci oluşturmak için komut kullanılır veritabanındaki tüm tabloları eklemek için kod içerir.

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

benim InitialCreate göç Up yöntem bu kod tarafından adlandırılan almıyor, beklediğim olmadığı şu şekildedir: benim özel IDatabaseInitializer yılında

kodudur. Bunun yerine, tüm tablolar Database.Create() yöntemi çağrıldığında oluşturulur. Çalıştırılacak InitialCreate geçişine ihtiyacım var çünkü saklı yordamları oluşturmak için ek kodum var.

Sorularım, yeni bir veritabanını nasıl programlı olarak oluşturabilirim ve tüm geçişleri (InitialCreate geçişi de dahil) nasıl çalıştırabilirim?

cevap

4

Aşağıdaki kod, soruda özetlenen bütünleştirme sınama senaryolarının gereksinimlerini karşılamamı sağladı, ancak kesinlikle daha iyi bir yol var mı?

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

Sadece "veritabanı oluştur" adımını kaldırın ve geçişleri kendi başlarına kullanın. GitHub üzerinde örnek bir proje koydum, ancak önemli bit

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

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