如何编写EF Migration脚本实现指定条件下中止数据库迁移
EF Code First 按条件终止迁移流程实现方案
实现逻辑分两类场景,按需选择即可:
方案1:全局拦截(代码触发迁移场景适用)
如果你的迁移是通过应用代码触发(比如启动时自动迁移、自定义迁移任务),最彻底的方式是继承DbMigrator重写更新方法,在所有迁移操作执行前先跑判定逻辑,条件命中直接返回,完全不会对数据库执行任何操作。
using System.Data.Entity.Migrations; public class ConditionalDbMigrator : DbMigrator { private readonly Func<bool> _abortCheck; public ConditionalDbMigrator(DbMigrationsConfiguration config, Func<bool> abortCheck) : base(config) { _abortCheck = abortCheck; } public override void Update() { if (_abortCheck()) return; base.Update(); } public override void Update(string targetMigration) { if (_abortCheck()) return; base.Update(targetMigration); } }
调用时替换默认的Migrator即可:
var config = new YourProjectMigrationsConfiguration(); // 这里写你自己的判定逻辑,比如读配置、判断当前环境、检查维护状态都可以 bool AbortMigration() { return bool.Parse(ConfigurationManager.AppSettings["BlockAllDbChanges"] ?? "false"); } var migrator = new ConditionalDbMigrator(config, AbortMigration); // 条件命中时这行不会执行任何数据库操作 migrator.Update();
注意:如果是用migrate.exe、dotnet ef migrations add/update这类官方命令行工具执行迁移,这个方案不生效,用下面的方案。
方案2:迁移脚本内判断(适配命令行迁移场景)
用命令行执行迁移时,直接在迁移类的Up/Down方法开头加判定逻辑即可,条件命中直接return,不会执行该迁移下的任何表结构/数据变更操作。
打开Migrations文件夹下对应迁移的代码文件,修改如下:
public partial class AddOrderTable : DbMigration { public override void Up() { // 判定条件为真时直接退出 if (ShouldSkipThisMigration()) return; // 原有迁移逻辑,比如建表、加字段、加索引等 // CreateTable( // "dbo.Orders", // c => new { // Id = c.Int(nullable: false, identity: true), // OrderNo = c.String(nullable: false) // }) // .PrimaryKey(t => t.Id); } public override void Down() { // 回滚逻辑加相同判断,避免误操作 if (ShouldSkipThisMigration()) return; // 原有回滚逻辑 // DropTable("dbo.Orders"); } private bool ShouldSkipThisMigration() { // 自定义判定逻辑,示例:当前连接字符串指向生产库时跳过迁移 var connStr = Database.Connection.ConnectionString; return connStr.Contains("Prod_DB"); } }
如果要对所有迁移统一生效,不用每个文件重复写判断,可以把判断逻辑抽成所有迁移类的公共基类,或者修改EF迁移的代码生成模板,自动生成判断逻辑。
小提示:条件命中时可以自己加日志输出,比如打印到控制台、写入本地日志文件,方便排查迁移未执行的原因。
内容的提问来源于stack exchange,提问作者Manikandan
相关产品推荐
相关产品推荐

