C# · 12月 30, 2021

c# – EF 5,代码优先 – 创建一个新的数据库并以编程方式运行所有迁移

@H_301_1@我正在使用实体框架代码第一次迁移,我有一个场景,我想运行一套集成测试.每次测试运行时,我想重新创建数据库,并应用所有迁移

步骤应该是:

>删除现有的测试数据库(如果有的话)
>创建一个新的测试数据库,并应用所有迁移
>种子数据

这是我已经将迁移添加到的现有项目,我使用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; }}