手动将DbContext提供给DbMigrator

Platform .NET 4.5和Entity Framework 6。

问题我有以下代码来执行迁移:

//The following function just returns an object of the Configuration() class //generated by code migrations var migratorConfig = currentMigrationProvider.CreateDbMigrationConfiguration(); var dbMigrator = new System.Data.Entity.Migrations.DbMigrator(migratorConfig); dbMigrator.Update(); 

问题是Update()函数尝试创建我的DbContext类的实例,并且由于一些好的原因,我需要手动创建上下文并将其提供给dbMigrator。 那可能吗? 怎么样?

是的,可以控制迁移和上下文。 如果您正在管理连接,这一点很重要。 该示例显示连接到2个不同的Dbs。 这有点令人费解。 所以我建立了一个小测试项目来演示如何。

 using System; using System.Data.Common; using System.Data.Entity; using System.Data.Entity.Infrastructure; using System.Data.Entity.Migrations; namespace Ef6Test { public class Program { public static void Main(string[] args) { ExecDb1(); ExecDB2(); ExecDbCtx3(); } private static void ExecDb1() { Database.SetInitializer(new MigrateDatabaseToLatestVersion()); WhichDb.DbName = "HACKDB1"; WhichDb.ConnType = ConnType.CtxViaDbConn; var sqlConn = GetSqlConn4DBName(WhichDb.DbName); var context = new Ef6Ctx(sqlConn); context.Database.Initialize(true); Console.WriteLine(WhichDb.DbName, context.Database.Exists() ); AddJunk(context); //sqlConn.Close(); //?? whatever other considerations, dispose of context etc... } private static void ExecDB2() { // yes other its default again reset this !!!! WhichDb.DbName = "HACKDB2"; WhichDb.ConnType = ConnType.CtxViaDbConn; var sqlConn2 = GetSqlConn4DBName(WhichDb.DbName); var context2 = new Ef6Ctx2(sqlConn2); Console.WriteLine(context2.Database.Exists()); Database.SetInitializer(new MigrateDatabaseToLatestVersion()); context2.Database.Initialize(true); Console.WriteLine(WhichDb.DbName, context2.Database.Exists()); AddJunk(context2); } private static void ExecDbCtx3() { Database.SetInitializer(new MigrateDatabaseToLatestVersion()); // Database.SetInitializer(new CreateDatabaseIfNotExists()); // Database.SetInitializer(null); WhichDb.ConnectionName = "AppCfgName"; WhichDb.ConnType = ConnType.CtxViaConnectionName; var context3 = new Ef6Ctx3(WhichDb.ConnectionName); context3.Database.Initialize(true); Console.WriteLine(WhichDb.ConnectionName, context3.Database.Exists()); AddJunk(context3); } public static class WhichDb { public static string DbName { get; set; } public static string ConnectionName { get; set; } public static ConnType ConnType { get; set; } } public enum ConnType { CtxViaDbConn, CtxViaConnectionName } private static void AddJunk(DbContext context) { var poco = new pocotest(); poco.f1 = DateTime.Now.ToString(); // poco.f2 = "Did somebody step on a duck?"; //comment in for second run context.Set().Add(poco); context.SaveChanges(); } public static DbConnection GetSqlConn4DBName(string dbName) { var sqlConnFact = new SqlConnectionFactory( "Data Source=localhost; Integrated Security=True; MultipleActiveResultSets=True"); var sqlConn = sqlConnFact.CreateConnection(dbName); return sqlConn; } } public class MigrationsContextFactory : IDbContextFactory { public Ef6Ctx Create() { switch (Program.WhichDb.ConnType) { case Program.ConnType.CtxViaDbConn: var sqlConn = Program.GetSqlConn4DBName(Program.WhichDb.DbName); // NASTY but it works return new Ef6Ctx(sqlConn); case Program.ConnType.CtxViaConnectionName: return new Ef6Ctx(Program.WhichDb.ConnectionName); default: throw new ArgumentOutOfRangeException(); } } } public class MigrationsContextFactory2 : IDbContextFactory { public Ef6Ctx2 Create() { switch (Program.WhichDb.ConnType) { case Program.ConnType.CtxViaDbConn: var sqlConn = Program.GetSqlConn4DBName(Program.WhichDb.DbName); // NASTY but it works return new Ef6Ctx2(sqlConn); case Program.ConnType.CtxViaConnectionName: return new Ef6Ctx2(Program.WhichDb.ConnectionName); default: throw new ArgumentOutOfRangeException(); } } } public class MigrationsContextFactory3 : IDbContextFactory { public Ef6Ctx3 Create() { switch (Program.WhichDb.ConnType) { case Program.ConnType.CtxViaDbConn: var sqlConn = Program.GetSqlConn4DBName(Program.WhichDb.DbName); // NASTY but it works return new Ef6Ctx3(sqlConn); case Program.ConnType.CtxViaConnectionName: return new Ef6Ctx3(Program.WhichDb.ConnectionName); default: throw new ArgumentOutOfRangeException(); } } } public class Ef6MigConf : DbMigrationsConfiguration { public Ef6MigConf() { AutomaticMigrationsEnabled = true; AutomaticMigrationDataLossAllowed = true; } } public class Ef6MigConf2 : DbMigrationsConfiguration { public Ef6MigConf2() { AutomaticMigrationsEnabled = true; AutomaticMigrationDataLossAllowed = true; } } public class Ef6MigConf3 : DbMigrationsConfiguration { public Ef6MigConf3() { AutomaticMigrationsEnabled = true; AutomaticMigrationDataLossAllowed = true; } } public class pocotest { public int Id { get; set; } public string f1 { get; set; } public string f2 { get; set; } // comment in for second run public string f2a { get; set; } // comment in for second run public string f3 { get; set; } // comment in for second run public string f5 { get; set; } // comment in for second run public string f6b { get; set; } // comment in for second run } public class Ef6Ctx : DbContext { public Ef6Ctx(DbConnection dbConn) : base(dbConn, true) { } public Ef6Ctx(string connectionName) : base(connectionName) { } public DbSet poco1s { get; set; } } public class Ef6Ctx2 : DbContext { public Ef6Ctx2(DbConnection dbConn) : base(dbConn, true) { } public Ef6Ctx2(string connectionName) : base(connectionName) { } public DbSet poco1s { get; set; } } }