C# EF 5,代码优先-创建一个新数据库并以编程方式运行所有迁移
我使用的是实体框架代码优先迁移,我有一个场景,我想运行一套集成测试。每次运行测试时,我都要重新创建数据库,并应用所有迁移 这些步骤应该是:C# EF 5,代码优先-创建一个新数据库并以编程方式运行所有迁移,c#,entity-framework,entity-framework-migrations,C#,Entity Framework,Entity Framework Migrations,我使用的是实体框架代码优先迁移,我有一个场景,我想运行一套集成测试。每次运行测试时,我都要重新创建数据库,并应用所有迁移 这些步骤应该是: 删除现有的测试数据库(如果有) 创建一个新的测试数据库,并应用所有迁移 种子数据 这是一个已添加迁移的现有项目,我使用Enable migrations命令创建了一个“InitialCreate”迁移,其中包含将所有表添加到数据库的代码 我的自定义IDatabaseInitializer中的代码如下: public void InitializeDataba
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;
}
}
public void初始化数据库(MyContext上下文)
{
//删除任何现有数据库,然后重新创建
context.Database.Delete();
var newDbConnString=context.Database.Connection.ConnectionString;
var connStringBuilder=new-SqlConnectionStringBuilder(newDbConnString);
var newDbName=connStringBuilder.InitialCatalog;
connStringBuilder.InitialCatalog=“master”;
//创建新的数据库
使用(var sqlConn=newsqlconnection(connStringBuilder.ToString()))
{
使用(var createDbCmd=sqlConn.CreateCommand())
{
createDbCmd.CommandText=“创建数据库”+newDbName;
sqlConn.Open();
createDbCmd.ExecuteOnQuery();
}
}
//等待30秒,以完全创建新数据库
//在我的桌面上大约需要4秒钟
var=0;
var dbOnline=false;
同时(尝试次数<30&!dbOnline)
{
if(IsDatabaseOnline(newDbConnString))
{
dbOnline=true;
}
其他的
{
尝试++;
睡眠(1000);
}
}
如果(!dbOnline)
抛出新的ApplicationException(string.Format(“等待新创建的数据库\“{0}\”联机的时间太长”,newDbName));
//应用所有迁移
var dbmigator=new dbmigator(new Configuration());
dbMigrator.Update();
//用数据播种
这个种子(上下文);
SaveChanges();
}
专用布尔IsDatabaseOnline(字符串连接字符串)
{
尝试
{
使用(var sqlConn=newsqlconnection(connString))
{
sqlConn.Open();
返回sqlConn.State==ConnectionState.Open;
}
}
捕获(SqlException)
{
返回false;
}
}
只需删除“创建数据库”步骤并自行使用迁移即可。我放了一个示例项目,但重要的是
Configuration config = new Configuration();
DbMigrator migrator = new DbMigrator(config);
foreach (string s in migrator.GetPendingMigrations())
{
migrator.Update(s);
}