c# - EF 5,Code First - 创建一个新数据库并以编程方式运行所有迁移

标签 c# entity-framework entity-framework-migrations

我正在使用 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();
}

此代码未调用我的 InitialCreate 迁移的 Up 方法,这不是我所期望的。相反,所有表都是在调用 Database.Create() 方法时创建的。我需要运行 InitialCreate 迁移,因为我在其中有额外的代码来创建存储过程。

所以我的问题是,如何以编程方式创建新数据库并运行所有迁移(包括 InitialCreate 迁移)?

最佳答案

以下代码使我能够满足问题中概述的集成测试场景的需求,但肯定有更好的方法吗?

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

关于c# - EF 5,Code First - 创建一个新数据库并以编程方式运行所有迁移,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15692584/

相关文章:

C# GUI 可编辑 DataGridView

c# - 枚举迭代?

c# - 为什么 Monitor.PulseAll 在信号线程中导致 "stepping stair"延迟模式?

c# - 静态事件与 C# 中的非静态事件相比如何?

.net - 您使用 Entity Framework 的经历如何?

c# - 在 Entity Framework Migration 中填写表格

datetime - EF 迁移 : Can't add DateTime column

c# - 如何在 ASP.NET Identity 中创建不同的用户类型?

c# - Linq to Entities 过滤器导航集合属性

c# - 如何在迁移中使用 DbContext?