EF6多数据库迁移报错:待处理显式迁移问题排查
解决EF Code First多上下文迁移报错及集中历史表问题
问题分析
你遇到的报错是因为EF默认会扫描所有已存在的__MigrationsHistory表记录,不管这些记录属于哪个上下文,导致生成新迁移时误判存在未应用的pending迁移。下面提供两种符合你需求的解决方案:
方案1:每个上下文独立维护迁移历史表
让每个上下文的迁移记录存储在单独的历史表中,互相隔离,避免干扰:
- 在每个上下文的
DbConfiguration构造函数中,指定唯一的迁移历史表名:
public PayrollDbConfiguration() { AutomaticMigrationsEnabled = false; MigrationsDirectory = @"Migrations\PayrollDb"; // 为当前上下文指定专属的迁移历史表名 SetHistoryContextFactory("System.Data.SqlClient", (connection, defaultSchema) => new HistoryContext(connection, defaultSchema) { TableName = "__PayrollMigrationsHistory" // 每个上下文使用不同的表名,比如__HRMigrationsHistory、__SalesMigrationsHistory等 }); }
- 生成和应用迁移时,必须指定对应的上下文和配置(以Package Manager Console为例):
# 生成Payroll上下文的迁移 Add-Migration InitialCreate -ConfigurationTypeName YourNamespace.PayrollDbConfiguration -ContextTypeName YourNamespace.PayrollDbContext # 应用Payroll上下文的迁移 Update-Database -ConfigurationTypeName YourNamespace.PayrollDbConfiguration -ContextTypeName YourNamespace.PayrollDbContext
这样每个上下文只会检查自己的历史表,不会读取其他上下文的迁移记录,也就不会出现误判pending迁移的问题。
方案2:用中心数据库的单个表管理所有迁移
如果要统一用中心数据库的单个表管理所有上下文的迁移,需要修正你之前的代码,确保EF正确区分不同上下文的迁移记录:
步骤1:创建自定义历史上下文
public class CentralHistoryContext : HistoryContext { public CentralHistoryContext(DbConnection connection, string defaultSchema) : base(connection, defaultSchema) { // 强制连接到中心数据库 Database.Connection.ConnectionString = Jamlite.Database.Properties.Settings.Default.DefaultCon; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // 确保EF通过ContextKey区分不同上下文的迁移记录(默认已包含此键,此处显式声明以明确逻辑) modelBuilder.Entity<HistoryRow>() .HasKey(h => new { h.MigrationId, h.ContextKey }); } }
步骤2:在每个上下文的配置中使用自定义历史上下文
public PayrollDbConfiguration() { AutomaticMigrationsEnabled = false; MigrationsDirectory = @"Migrations\PayrollDb"; SetHistoryContextFactory("System.Data.SqlClient", (connection, defaultSchema) => new CentralHistoryContext(connection, defaultSchema)); }
步骤3:清理旧的历史表
删除所有业务数据库中已自动创建的__MigrationsHistory表,确保所有迁移记录只写入中心数据库的历史表。
步骤4:重新生成并应用迁移
同样使用指定上下文和配置的命令生成、应用迁移,EF会自动通过ContextKey字段区分不同上下文的迁移记录,不会出现pending迁移误判。
内容的提问来源于stack exchange,提问作者Ansel Cadien
相关产品推荐
相关产品推荐

