Непревзойденная обработка файлов через контейнер ForEach Loop
У меня есть несколько обработанных и необработанных файлов в моей Исходной папке, а имена всех обработанных файлов хранятся в таблице. Как я могу сопоставить имена файлов исходной папки и таблицы до ForEach Loop Container и обрабатывать только несопоставленные файлы.
2 ответа
Приведенное ниже решение немного сложнее, но это лучшее, что я могу придумать.
ШАГ 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" в ваш контейнер цикла по каждому элементу.
Настройте сопоставление параметров, как показано ниже:
Используйте приведенный ниже скрипт в качестве своего SQL-выражения:
DECLARE @ToProcess VARCHAR(1)
IF NOT EXISTS(SELECT [FileNames] FROM [YourFilesTable] WHERE FileNames = ?)
SET @ToProcess = 'Y'
SELECT @ToProcess AS ToProcess
Установите ResultSet в одну строку, как показано ниже:
Настройте набор результатов, как показано ниже:
В задаче "Выполнение SQL" настройте ограничение приоритета, как показано ниже:
Контейнер цикла Foreach должен выглядеть следующим образом:
Перед циклом Foreach используйте задачу "Сценарий", чтобы сохранить имена необработанных файлов в переменной объекта SSIS, а затем выполните итерацию по этой переменной, чтобы загрузить новые файлы, какими вы уже являетесь. Создайте переменную объекта и добавьте ее в ReadWriteVariables
поле задачи скрипта. Если вы используете переменную SSIS для хранения пути к папке с исходными файлами, как это сделано ниже, добавьте это в ReadOnlyVariables
поле. Цикл Foreach должен будет использовать тип перечислителя Foreach From Variable Enumerator. В поле "Переменная" на странице "Коллекция" добавьте переменную объекта, которая заполняется в задаче "Сценарий". Как вы, вероятно, уже делаете, добавьте строковую переменную в индекс 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();