【发布时间】:2016-07-03 19:07:26
【问题描述】:
EntityFramework 迁移在切换到新上下文后变得无用。 DbMigrator 正在使用来自第一个数据库实例的 Pending Migrations 列表,这意味着没有迁移应用到其他数据库,这会导致 Seed() 期间出现错误;
- 带有 EF 6 的 C# .NET 4.5 MVC 项目
- MS SQL Server 2014,同一数据库模型的多个实例。
- 带有迁移的 CodeFirst 方法。
- DbContext 初始化程序设置为 null。
在应用程序启动时,我们有自定义 Db 初始化来创建和更新数据库。 CreateDatabaseIfNotExists 正在按预期工作,新数据库已应用所有迁移。但是,MigrateDatabaseToLatestVersion 初始化程序和我们的自定义初始化程序都无法更新列表中第一个以外的数据库。
foreach (var connectionString in connectionStrings)
{
using (var context = new ApplicationDbContext(connectionString))
{
//Create database
var created = context.Database.CreateIfNotExists();
var conf = new Workshop.Migrations.Configuration();
var migrator = new DbMigrator(conf);
migrator.Update();
//initial values
conf.RunSeed(context);
}
}
-
context.Database.CreateIfNotExists();工作正常。 -
migrator.GetLocalMigrations()总是返回正确的值。 -
migrator.GetPendingMigrations()第一个数据库返回后 空列表。 -
migrator.GetDatabaseMigrations()是挂起迁移的镜像, 在第一个数据库之后,它包含空数据库的完整列表事件。 - 从 Db 实例获取数据 (
context.xxx.ToList()) 确认连接已建立且正常工作,并链接到正确的实例。
使用migrator.Update("migration_name"); 强制更新到最近的迁移不会改变任何事情。根据我通过阅读 EF 源代码收集到的信息,它会自行检查挂起的迁移列表,这会给出错误的结果。
引擎盖下似乎有一些缓存,但我不知道如何重置它。
有没有办法在多个数据库上执行迁移,还是 EF 中的另一个“设计错误”?
编辑:
真正的问题是DbMigrator 创建新的上下文供自己使用。它通过默认的无参数构造函数完成,在我的例子中,它回退到web.Config 中的默认(第一个)连接字符串。
我没有看到这个问题的好的解决方案,但在我的情况下,原始的解决方法是临时编辑默认连接字符串:
var originalConStr = WebConfigurationManager.ConnectionStrings["ApplicationDbContext"].ConnectionString;
var setting = WebConfigurationManager.ConnectionStrings["ApplicationDbContext"];
var fi = typeof(ConfigurationElement).GetField("_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
//disable readonly flag on field
fi.SetValue(setting, false);
setting.ConnectionString = temporaryConnectionString; //now it works
//DO STUFF
setting.ConnectionString = originalConStr; //revert changes
作弊来自:How do I set a connection string config programatically in .net?
我仍然希望有人能找到真正的解决方案,所以现在我会避免自我回答。
【问题讨论】:
标签: c# entity-framework ef-code-first entity-framework-migrations