开发阶段如何通过命令行让DBUP仅重跑新脚本而非历史脚本
这个需求其实DBUp本身就提供了灵活的扩展方式来实现,结合它的脚本追踪和加载机制,我给你分享几个实用的方案:
方案1:通过脚本标识过滤,仅加载开发中脚本
DBUp允许你在加载脚本时添加过滤条件,我们可以给开发中的脚本加上统一的前缀(比如Dev_或者WIP_),然后通过命令行开关来触发这个过滤逻辑,这样就只会加载并运行这些标记过的脚本,历史脚本因为没有标识会被自动忽略。
举个代码示例:
using System.Reflection; using DbUp; var connectionString = "Your_Database_Connection_String"; var upgraderBuilder = DeployChanges.To.SqlDatabase(connectionString); // 检查命令行是否传入开发模式开关 if (args.Contains("--dev-mode", StringComparer.OrdinalIgnoreCase)) { // 仅加载包含"Dev_"前缀的嵌入式脚本 upgraderBuilder = upgraderBuilder .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly(), scriptName => scriptName.Contains("Dev_")) .LogToConsole(); } else { // 正式发布模式:加载所有嵌入式脚本 upgraderBuilder = upgraderBuilder .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly()) .LogToConsole(); } var upgrader = upgraderBuilder.Build(); var result = upgrader.PerformUpgrade(); if (!result.Successful) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(result.Error); Console.ResetColor(); return -1; } Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Success!"); Console.ResetColor(); return 0;
使用方式:
- 开发时运行:
YourDbUpApp.exe --dev-mode - 正式发布时直接运行:
YourDbUpApp.exe
这种方式的好处是完全利用DBUp的默认Journal机制,已执行的开发脚本会被记录到数据库,不会重复执行;如果需要修改脚本重新运行,只要删除SchemaVersions表中对应脚本的记录即可。
方案2:命令行指定单个脚本,强制重新运行
如果你只需要调试某个特定脚本,并且希望强制重新执行它(不管是否已经在Journal中记录),可以通过命令行参数指定脚本路径,同时临时禁用Journal来实现:
using DbUp; var connectionString = "Your_Database_Connection_String"; var upgraderBuilder = DeployChanges.To.SqlDatabase(connectionString); // 检查是否传入强制重跑开关和脚本路径 var devReRunIndex = Array.IndexOf(args, "--dev-re-run"); if (devReRunIndex != -1 && args.Length > devReRunIndex + 1) { var targetScriptPath = args[devReRunIndex + 1]; upgraderBuilder = upgraderBuilder .WithScriptFromFile(targetScriptPath) .WithoutJournaling() // 禁用Journal,强制运行该脚本 .LogToConsole(); } else { // 正式发布模式逻辑 upgraderBuilder = upgraderBuilder .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly()) .LogToConsole(); } var upgrader = upgraderBuilder.Build(); var result = upgrader.PerformUpgrade(); // 后续结果处理同上...
使用方式:YourDbUpApp.exe --dev-re-run ./Scripts/MyDevScript.sql
这个方案适合单脚本快速调试,不会影响任何历史脚本的执行记录,也不会触发历史脚本的运行。
方案3:按版本号筛选脚本(适合版本化开发流程)
如果你的脚本是按版本号命名的(比如V1_0_0__InitialSetup.sql、V1_0_1__NewFeature.sql),可以通过命令行指定目标版本号,只加载对应版本的脚本:
using System.Reflection; using DbUp; var connectionString = "Your_Database_Connection_String"; var upgraderBuilder = DeployChanges.To.SqlDatabase(connectionString); var targetVersionIndex = Array.IndexOf(args, "--target-version"); if (targetVersionIndex != -1 && args.Length > targetVersionIndex + 1) { var targetVersion = args[targetVersionIndex + 1]; upgraderBuilder = upgraderBuilder .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly(), scriptName => scriptName.StartsWith($"V{targetVersion}__")) .LogToConsole(); } else { // 正式发布模式逻辑 upgraderBuilder = upgraderBuilder .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly()) .LogToConsole(); } var upgrader = upgraderBuilder.Build(); var result = upgrader.PerformUpgrade(); // 后续结果处理同上...
使用方式:YourDbUpApp.exe --target-version 1.0.1
这种方式贴合版本化的发布流程,开发时可以只运行当前迭代的版本脚本,避免执行所有历史脚本。
核心原理提醒
DBUp默认会将已执行的脚本名称记录到数据库的SchemaVersions表中,只要脚本名称不变,即使多次运行升级程序,也不会重复执行历史脚本。所以我们的核心思路就是在开发模式下,限制加载的脚本范围,只包含当前正在开发的脚本,这样既保证了历史脚本不重复执行,又能反复调试当前脚本。
内容的提问来源于stack exchange,提问作者Shawson

