DBUP脚本执行顺序异常求助:目录排序规则未生效
DBUP脚本执行顺序异常问题
我正在试用DBUP,但无法使其正常工作。我将脚本拆分到不同目录中,并为目录添加了数字前缀以指定执行顺序。据我了解,DBUP应先按字典序处理目录,再处理目录内的文件,但实际并非如此——它似乎将所有文件视为在同一目录中,仅按文件名字典序执行,导致数据脚本尝试向尚未创建的表插入数据。
我的代码如下:
var upgrader = DeployChanges.To.SqlDatabase(connectionString) .WithScriptsFromFileSystem(Path.Combine(dbScripts, "00-PreDeployment")) .WithScriptsFromFileSystem(Path.Combine(dbScripts, "01-Tables")) .WithScriptsFromFileSystem(Path.Combine(dbScripts, "02-Views")) .WithScriptsFromFileSystem(Path.Combine(dbScripts, "03-Functions")) .WithScriptsFromFileSystem(Path.Combine(dbScripts, "04-StoredProcedures")) .WithScriptsFromFileSystem(Path.Combine(dbScripts, "05-Data")) .JournalToSqlTable("dbo", "SchemaVersion") .LogToConsole() .Build();
例如:01-Tables目录下的Statuses.sql负责创建Status表,05-Data目录下的Add_Status.sql负责填充该表。我预期先执行Statuses.sql再执行Add_Status.sql,但实际Add_Status.sql因文件名以'A'开头,比'S'开头的Statuses.sql先执行,导致表未创建就插入数据。请问我是否遗漏了配置?难道只能给所有脚本添加目录顺序前缀来解决?
解决方案
DBUP默认会把所有通过WithScriptsFromFileSystem添加的脚本合并到一个集合中,然后仅按文件名的字典序排序,不会保留目录的执行优先级——这就是问题的核心原因。
你有两种更优的解决方式,无需给每个脚本添加前缀:
1. 自定义脚本排序规则
使用WithScriptsSortedBy方法指定排序逻辑,让脚本先按所在目录的名称排序,再按文件名排序,确保目录的数字前缀先生效。修改后的代码如下:
var upgrader = DeployChanges.To.SqlDatabase(connectionString) .WithScriptsFromFileSystem(Path.Combine(dbScripts, "00-PreDeployment")) .WithScriptsFromFileSystem(Path.Combine(dbScripts, "01-Tables")) .WithScriptsFromFileSystem(Path.Combine(dbScripts, "02-Views")) .WithScriptsFromFileSystem(Path.Combine(dbScripts, "03-Functions")) .WithScriptsFromFileSystem(Path.Combine(dbScripts, "04-StoredProcedures")) .WithScriptsFromFileSystem(Path.Combine(dbScripts, "05-Data")) // 先按目录名排序,再按文件名排序 .WithScriptsSortedBy(script => $"{Path.GetDirectoryName(script.Path)}_{script.Name}") .JournalToSqlTable("dbo", "SchemaVersion") .LogToConsole() .Build();
2. 按目录分批执行升级
如果需要严格保证前一个目录的所有脚本执行完成后,再执行下一个目录的脚本,可以拆分升级逻辑,分批次执行:
// 执行预部署脚本 var preDeployUpgrader = DeployChanges.To.SqlDatabase(connectionString) .WithScriptsFromFileSystem(Path.Combine(dbScripts, "00-PreDeployment")) .JournalToSqlTable("dbo", "SchemaVersion") .LogToConsole() .Build(); var preDeployResult = preDeployUpgrader.PerformUpgrade(); if (!preDeployResult.Successful) { // 处理失败逻辑,比如输出错误信息并终止 Console.WriteLine(preDeployResult.Error); return; } // 执行表脚本 var tablesUpgrader = DeployChanges.To.SqlDatabase(connectionString) .WithScriptsFromFileSystem(Path.Combine(dbScripts, "01-Tables")) .JournalToSqlTable("dbo", "SchemaVersion") .LogToConsole() .Build(); var tablesResult = tablesUpgrader.PerformUpgrade(); if (!tablesResult.Successful) { Console.WriteLine(tablesResult.Error); return; } // 依次执行视图、函数、存储过程、数据脚本的升级 // 代码逻辑与上述示例一致
这种方式完全保证了目录的执行顺序,适合对脚本执行先后有严格要求的场景。
内容的提问来源于stack exchange,提问作者Jack Thor
相关产品推荐
相关产品推荐

