我正在使用实体框架代码第一次迁移,我有一个场景,我想运行一套集成测试.每次测试运行时,我想重新创建数据库,并应用所有迁移
步骤应该是:
>删除现有的测试数据库(如果有的话)
>创建一个新的测试数据库,并应用所有迁移
>种子数据
这是我已经将迁移添加到的现有项目,我使用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迁移才能运行,因为我有其他代码来创建存储过程.
解决方法
以下代码允许我满足我在问题中概述的集成测试场景的需求,但肯定有更好的方法?
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; } }