EF 5, Code First - Създайте нова база данни и стартирайте всички миграции програмно

Използвам миграции на Entity Framework Code First и имам сценарий, при който искам да изпълня набор от интеграционни тестове. Всеки път, когато се изпълняват тестовете, искам да създам отново базата данни и да приложа всички миграции

Стъпките трябва да бъдат:

  1. Премахнете съществуващата тестова база данни (ако има такава)
  2. Създайте нова тестова база данни и приложете всички миграции
  3. Данни за семена

Това е съществуващ проект, към който добавих миграции, и използвах командата Enable-Migrations, за да създам миграция „InitialCreate“, която съдържа код за добавяне на всички таблици към моята база данни.

Кодът в моя персонализиран 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();
}

Методът Up на моята миграция InitialCreate не се извиква от този код, което не е това, което очаквах. Вместо това, всички таблици се създават, когато се извика методът Database.Create(). Имам нужда от стартиране на миграцията InitialCreate, защото имам допълнителен код там за създаване на съхранени процедури.

Въпросът ми е как да създам програмно нова база данни и да изпълня всички миграции (включително миграцията InitialCreate)?


person Matt    schedule 28.03.2013    source източник


Отговори (2)


Следният код ми позволи да отговоря на нуждите на моя сценарий за тестване на интеграция, описан във въпроса, но със сигурност има по-добър начин?

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;
    }
}
person Matt    schedule 29.03.2013

Просто премахнете стъпката „създаване на база данни“ и използвайте миграциите сами. Поставих примерен проект в GitHub, но важното е

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

foreach (string s in migrator.GetPendingMigrations())
{
    migrator.Update(s);
}
person mike mckechnie    schedule 19.09.2015