SSIS中C#脚本任务未遍历全部26个文件的问题求助
问题分析与解决
你的核心问题是仅记录了上一个处理的文件,而非所有已处理文件,导致循环时来回读取最新的两个文件,无法遍历全部26个文件:
每次循环中,脚本会重新读取所有文件并按时间戳降序排列,然后取第一个不等于LastProcessedFile的文件。第一次取最新文件,第二次取次新文件,第三次又会取最新文件(因为此时LastProcessedFile是次新文件),以此类推,循环26次就只会重复读取这两个文件。
修复步骤
1. 调整包变量
将原有的User::LastProcessedFile变量替换为User::ProcessedFiles(字符串类型,初始值为空),用来存储所有已处理的文件路径(用分号;分隔)。
2. 修改脚本任务代码
替换现有脚本逻辑,改为跟踪所有已处理文件,每次从剩余未处理文件中选取下一个:
public void Main() { bool fireAgain = true; string sourceFolder = Dts.Variables["User::SourceFolder"].Value.ToString(); string fileExtension = Dts.Variables["User::FileExtension"].Value.ToString(); string processedFiles = Dts.Variables["User::ProcessedFiles"].Value.ToString(); // 把已处理文件转为集合,快速判断是否已处理 HashSet<string> processedSet = new HashSet<string>(); if (!string.IsNullOrEmpty(processedFiles)) { foreach (string file in processedFiles.Split(';')) { processedSet.Add(file.Trim()); } } string[] files = Directory.GetFiles(sourceFolder, "*" + fileExtension); Dictionary<string, DateTime> fileTimestamps = new Dictionary<string, DateTime>(); foreach (string file in files) { // 跳过已处理的文件 if (processedSet.Contains(file)) continue; string fileName = Path.GetFileNameWithoutExtension(file); // 避免文件名长度不足导致报错 if (fileName.Length < 14) continue; string fileTimestamp = fileName.Substring(fileName.Length - 14, 14); DateTime timestamp; if (DateTime.TryParseExact(fileTimestamp, "yyyyMMddHHmmss", null, System.Globalization.DateTimeStyles.None, out timestamp)) { fileTimestamps.Add(file, timestamp); } } // 按时间戳降序,取第一个未处理的文件 var nextFile = fileTimestamps.OrderByDescending(x => x.Value).FirstOrDefault(); if (nextFile.Key != null) { Dts.Variables["User::LatestFile"].Value = nextFile.Key; // 更新已处理文件列表 if (string.IsNullOrEmpty(processedFiles)) { Dts.Variables["User::ProcessedFiles"].Value = nextFile.Key; } else { Dts.Variables["User::ProcessedFiles"].Value = processedFiles + ";" + nextFile.Key; } // 输出调试日志,方便排查 Dts.Events.FireInformation(0, "Script Task", $"Processing file: {nextFile.Key}", string.Empty, 0, ref fireAgain); Dts.TaskResult = (int)ScriptResults.Success; } else { MessageBox.Show("No new files left to process.", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information); Dts.TaskResult = (int)ScriptResults.Failure; } }
3. 调整Foreach循环配置
不要设置固定26次循环,改为循环直到脚本任务返回Failure:
- 将Foreach循环的“EvalExpression”设置为检查脚本任务的执行结果,或者使用“For Loop”容器,设置循环条件为
@[User::ProcessedFiles]未包含所有文件,或直接循环直到脚本任务失败(无文件可处理)。
4. 优化数据流分支(可选)
如果26个文件的结构一致,不需要保留26个数据流分支,只用一个数据流任务即可,每次循环加载User::LatestFile指向的文件。如果文件结构不同,需在数据流分支前添加“优先约束”,根据LatestFile的文件名判断执行对应分支。
调试技巧
- 在脚本中添加
Dts.Events.FireInformation输出日志,可在SSIS的“执行结果”窗口查看每次循环的处理文件信息。 - 给脚本任务设置断点,调试时查看
processedSet、fileTimestamps等变量的内容,确认逻辑是否符合预期。
内容的提问来源于stack exchange,提问作者Manoj Sai
相关产品推荐
相关产品推荐

