通过 ForEach 循环容器处理不匹配的文件
Unmatched Files Processing through ForEach Loop Container
我的源文件夹中有一些已处理和未处理的文件以及文件名
所有处理过的文件都存储在 table 中。如何在 ForEach 循环容器之前匹配源文件夹和 table 的文件名,并仅处理不匹配的文件。
下面的解决方案有点复杂,但这是我能想到的最好的解决方案。
第 1 步:创建 2 个变量,均为字符串。
a)CurrentFile: This will be used for your Foreach Loop Container collection value
b)ToProcess: This will be used to map the result set an Execute SQL Task explained
below
第 2 步:将执行 SQL 任务添加到您的 Foreach 循环容器中。
配置参数映射如下图:
使用下面的脚本作为您的 SQL 语句:
DECLARE @ToProcess VARCHAR(1)
IF NOT EXISTS(SELECT [FileNames] FROM [YourFilesTable] WHERE FileNames = ?)
SET @ToProcess = 'Y'
SELECT @ToProcess AS ToProcess
将结果集设置为单行,如下所示:
如下所示配置结果集:
在执行 SQL 任务上,配置优先约束,如下所示:
您的 Foreach 循环容器应如下所示:
在 Foreach 循环之前,使用脚本任务将未处理文件的名称存储在 SSIS 对象变量中,然后遍历此变量以按原样加载新文件。创建一个对象变量并将其添加到脚本任务的 ReadWriteVariables
字段中。如果您使用 SSIS 变量来保存源文件的文件夹路径,如下所示,请将其添加到 ReadOnlyVariables
字段中。 Foreach 循环将需要使用 Foreach From Variable Enumerator 枚举器类型。在 Collection 页面上的 Variable 字段中,添加在 Script Task 中填充的对象变量。正如您可能已经在做的那样,在变量映射窗格的索引 0 处添加一个字符串变量,并将此变量设置为连接管理器上 ConnectionString
属性 的表达式,假设这是一个平面文件联系。如果这是 excel,请更改 ExcelFilePath
属性 以使用此变量作为表达式。脚本任务的示例代码和引用的命名空间如下,使用 C#。
using System.Linq;
using System.Data.SqlClient;
using System.IO;
using System.Collections.Generic;
using System.Data;
string connString = @"Data Source=YourSQLServer;Initial Catalog=YourDatabase;Integrated Security=SSPI;";
string cmdText = @"SELECT DISTINCT ColumnWithFileNames FROM YourDatabase.YourSchema.YourTable";
string sourceFolder = Dts.Variables["User::SourceFilePath"].Value.ToString();
//create DirectoryInfo object from source folder
DirectoryInfo di = new DirectoryInfo(sourceFolder);
List<string> processedFiles = new List<string>();
List<string> newFiles = new List<string>();
//get names of already processed files stored in tavle
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
//data set name does not need to relate to name of table storing processed files
DataSet ds = new DataSet("ProcessedFiles");
SqlDataAdapter da = new SqlDataAdapter(cmdText, conn);
da.Fill(ds, "ProcessedFiles");
foreach (DataRow dr in ds.Tables["ProcessedFiles"].Rows)
{
processedFiles.Add(dr[0].ToString());
}
}
foreach (FileInfo fi in di.EnumerateFiles())
{
//only add files not already processed
if (!processedFiles.Contains(fi.FullName))
{
newFiles.Add(fi.FullName);
}
}
//populate SSIS object variable with unprocessed files
Dts.Variables["User::ObjVar"].Value = newFiles.ToList();
我的源文件夹中有一些已处理和未处理的文件以及文件名 所有处理过的文件都存储在 table 中。如何在 ForEach 循环容器之前匹配源文件夹和 table 的文件名,并仅处理不匹配的文件。
下面的解决方案有点复杂,但这是我能想到的最好的解决方案。
第 1 步:创建 2 个变量,均为字符串。
a)CurrentFile: This will be used for your Foreach Loop Container collection value
b)ToProcess: This will be used to map the result set an Execute SQL Task explained
below
第 2 步:将执行 SQL 任务添加到您的 Foreach 循环容器中。
配置参数映射如下图:
使用下面的脚本作为您的 SQL 语句:
DECLARE @ToProcess VARCHAR(1)
IF NOT EXISTS(SELECT [FileNames] FROM [YourFilesTable] WHERE FileNames = ?)
SET @ToProcess = 'Y'
SELECT @ToProcess AS ToProcess
将结果集设置为单行,如下所示:
如下所示配置结果集:
在执行 SQL 任务上,配置优先约束,如下所示:
您的 Foreach 循环容器应如下所示:
在 Foreach 循环之前,使用脚本任务将未处理文件的名称存储在 SSIS 对象变量中,然后遍历此变量以按原样加载新文件。创建一个对象变量并将其添加到脚本任务的 ReadWriteVariables
字段中。如果您使用 SSIS 变量来保存源文件的文件夹路径,如下所示,请将其添加到 ReadOnlyVariables
字段中。 Foreach 循环将需要使用 Foreach From Variable Enumerator 枚举器类型。在 Collection 页面上的 Variable 字段中,添加在 Script Task 中填充的对象变量。正如您可能已经在做的那样,在变量映射窗格的索引 0 处添加一个字符串变量,并将此变量设置为连接管理器上 ConnectionString
属性 的表达式,假设这是一个平面文件联系。如果这是 excel,请更改 ExcelFilePath
属性 以使用此变量作为表达式。脚本任务的示例代码和引用的命名空间如下,使用 C#。
using System.Linq;
using System.Data.SqlClient;
using System.IO;
using System.Collections.Generic;
using System.Data;
string connString = @"Data Source=YourSQLServer;Initial Catalog=YourDatabase;Integrated Security=SSPI;";
string cmdText = @"SELECT DISTINCT ColumnWithFileNames FROM YourDatabase.YourSchema.YourTable";
string sourceFolder = Dts.Variables["User::SourceFilePath"].Value.ToString();
//create DirectoryInfo object from source folder
DirectoryInfo di = new DirectoryInfo(sourceFolder);
List<string> processedFiles = new List<string>();
List<string> newFiles = new List<string>();
//get names of already processed files stored in tavle
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
//data set name does not need to relate to name of table storing processed files
DataSet ds = new DataSet("ProcessedFiles");
SqlDataAdapter da = new SqlDataAdapter(cmdText, conn);
da.Fill(ds, "ProcessedFiles");
foreach (DataRow dr in ds.Tables["ProcessedFiles"].Rows)
{
processedFiles.Add(dr[0].ToString());
}
}
foreach (FileInfo fi in di.EnumerateFiles())
{
//only add files not already processed
if (!processedFiles.Contains(fi.FullName))
{
newFiles.Add(fi.FullName);
}
}
//populate SSIS object variable with unprocessed files
Dts.Variables["User::ObjVar"].Value = newFiles.ToList();