【问题标题】:SSIS excluding multiple items in a foreach loopSSIS在foreach循环中排除多个项目
【发布时间】:2020-04-14 12:41:52
【问题描述】:

我有一个包含可变数量文件夹的文件系统 这些文件夹可能包含也可能不包含用于进一步处理的文件 我希望从处理中排除某些文件夹 排除文件夹列表是逗号分隔的变量 分隔变量中包含的排除文件夹的数量可能会发生变化。
例如,当前分隔变量为“已处理、已排除、未知”
稍后,分隔变量可能看起来像“已处理、已排除、未知、下载”

我发现这个链接“在 Foreach 循环中跳过项目”只要排除的文件夹是硬编码的,它就可以工作 https://www.timmitchell.net/post/2009/09/16/skipping-items-in-a-foreach-loop/

例如,优先约束当前被硬编码为: FINDSTRING(@[User::FullFileName], "unknown",1) == 0

我的问题是: 1)将分隔字符串拆分为离散值的最佳方法 2) 根据排除文件夹列表评估 foreach 变量(在我的示例中称为 FullFileName)的最佳方法

【问题讨论】:

    标签: foreach ssis multivalue


    【解决方案1】:

    与 Tim 的好帖子类似的逻辑(我没有安装 SSIS,但我有 BimlStudio,所以请接受 SSIS 对象的不同图标)。

    3 个变量

    • CurrentFilename 字符串 - 这将包含当前文件名,可能包含也可能不包含排除值
    • ExclusionList 字符串 - 您要排除的文件夹的分隔字符串
    • IncludeCurrent boolean - False,我们将覆盖每个循环

    在 Foreach 文件循环中,我将使用脚本任务,因为它将是拆分 ExclusionList 以及执行文件系统测试的最有效方法。运行脚本任务的结果是我们将@[User::IncludeCurrent]的值设置为true或false。

    脚本任务和数据流任务之间的先例约束逻辑将从参考帖子简化为 @[User::IncludeCurrent]

    如果条件满足,我们执行 DFT 任务。否则,我们跳过它。

    包含测试

    您需要将 CurrentFilename 和 ExclusionList 作为只读变量传递给脚本任务。 IncludeCurrent 将作为读/写变量传递。

    // use the .net native split method to split on commas
    var fileList = Dts.Variables["ExclusionList"].Value.Split(new Char[] {','});
    
    // We could inline this for the next operation but you might have need for this elsewhere
    string currentFilename = Dts.Variables["CurrentFilename"].Value.ToString();
    
    // https://stackoverflow.com/questions/500925/check-if-a-string-contains-an-element-from-a-list-of-strings
    bool isFound = fileList.Any(s=>currentFileName.Contains(s));
    
    // Assign the results back to our SSIS scoped variable
    Dts.Variables["IncludeCurrent"].Value = isFound;
    

    关于 Raj More 提案的说明

    SPLIT_STRING 假定 SQL Server 2016+。作为一名顾问,我希望我可以依靠可用的最新功能,但通常情况并非如此。

    我相信您在使用 double for each loop 方法时可能遇到的挑战是内部记录集(查询的拆分列表)在第一次通过后被标记为已用完,因此您需要将此方法修改为 FELC 所有文件 - > OLE DB 查询 -> FELC 过滤器

    如果您有比纯字符串匹配更复杂的测试,脚本方法将提供最大的灵活性。

    【讨论】:

    • 我同意,蒂姆的帖子很棒。感谢您花时间回答我的问题。我会在早上解决这个问题,但是您使用脚本任务跟踪指出的方法以及我最初的想法。再次感谢!汤姆
    【解决方案2】:

    我将连接到数据库,执行 SPLIT_STRING,将结果放回对象中,然后在每个文件夹名称上使用 for-each loop.. 这样您将有两个 for-each 循环,外部循环用于查找匹配项,以及用于忽略子文件夹的内部。

    另外,请记住在 SSIS 中进行字符串比较时要注意区分大小写。

    【讨论】:

    • 谢谢你,拉吉!!!关于区分大小写的好点......肯定会错过那个。可能会尝试其他方法。再次感谢您抽出宝贵时间。
    【解决方案3】:

    感谢所有回答我问题的人。这是我降落的地方。我确信这可以改进。没有你们,我绝对做不到!!!!谢谢!

    创建项目变量 EFTFileSystem_FoldersToBeExcludedFromPolling 定义为字符串。逗号分隔。示例“已处理,错误” EFTFileSystem_NewFileName - 从 SSIS 为每个循环容器单个值填充。示例“c:\effy\bozo\SideShowBob.txt” EFTFileSystem_IsValidNewFile - 如果文件在有效文件夹中,脚本任务将返回完整路径。示例“c:\effy\bozo\KrustyGood.txt”

    添加和配置“Foreach 循环容器” 在收藏选项卡中 将“检索文件名”设置为完全限定 选择遍历子文件夹 在变量映射选项卡中 将变量设置为 User::EFTFileSystem_NewFileName

    在“Foreach 循环容器”内 创建脚本任务 ReadOnlyVariables = User::EFTFileSystem_FoldersToBeExcludedFromPolling,User::EFTFileSystem_NewFileName ReadWriteVariables = User::EFTFileSystem_IsValidNewFile

    编辑脚本任务 添加到命名空间:使用 System.Linq;

        public void Main()
        {
      // TODO: Add your code here
    
      // use the .net native split method to split on commas
      string Bob = Dts.Variables["EFTFileSystem_FoldersToBeExcludedFromPolling"].Value.ToString();
      var fileList = Bob.Split(new Char[] { ',' });
    
      // We could inline this for the next operation but you might have need for this elsewhere
      string currentFilename = Dts.Variables["EFTFileSystem_NewFileName"].Value.ToString();
    
      // https://stackoverflow.com/questions/500925/check-if-a-string-contains-an-element-from-a-list-of-strings
      bool isFound = fileList.Any(s => currentFilename.Contains(s));
    
    
      // Assign the results back to our SSIS scoped variable
      Dts.Variables["EFTFileSystem_IsValidNewFile"].Value = !isFound;
    
      Dts.TaskResult = (int)ScriptResults.Success;
    
    }
    

    【讨论】:

      猜你喜欢
      • 2020-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多