Ниже приведен обзор процесса с парой задач скрипта C #, использованных в этом примере. Для задач «Сценарий» обязательно добавьте правильные ссылки, как указано ниже, с указанием операторов using
в начале каждого раздела кода.
- Добавить задачу «Выполнение SQL» в начало потока управления. Имена файлов из текущего выполнения будут храниться в таблице, которая будет создана в этой задаче. Пример SQL для этого ниже. Это проверяет, существует ли таблица, удаляет ее, если она существует, а затем создает ее.
- Вероятно, у вас уже есть имя файла для каждой итерации, хранящееся в переменной, но если нет, добавьте строковую переменную в индекс 0 цикла Foreach. Это можно сделать на панели «Сопоставления переменных».
- В цикле Foreach добавьте задачу Script после всех компонентов. Добавьте строковую переменную, содержащую имя файла, в поле
ReadOnlyVariables
. Эта задача скрипта (использует C #) вставит имя файла, использованное в каждой итерации, в таблицу, которая будет использоваться позже. В то время как выполнение вставки с помощью C # немного сложнее, чем просто задача «Выполнение SQL», свойство FileInfo.Name
можно использовать для обеспечения сохранения только имени файла, в отличие от имени файла с путем.
- После цикла по каждому элементу создайте еще одну задачу сценария. Если для хранения имени выходной папки и префикса файла используются переменные, добавьте их в поле
ReadOnlyVariables
, как и раньше. Код для этого также ниже. Сначала имена файлов из текущего выполнения извлекаются и сохраняются в списке currentExecutionFiles
. Файлы в выходном каталоге затем перечисляются, и все файлы с префиксом, которые не использовались в текущем выполнении пакета, удаляются.
- Это необязательно, но я бы порекомендовал добавить еще одну задачу «Выполнение SQL» в конце пакета, чтобы удалить таблицу с именами файлов. Для этого можно просто использовать оператор
DROP
из первой задачи «Выполнение SQL».
CREATE и DROP DDL для выполнения задачи SQL:
IF (OBJECT_ID(N'DATABASE.SCHEMA.FILES') IS NOT NULL)
BEGIN
DROP TABLE DATABASE.SCHEMA.FILES
END;
CREATE TABLE DATABASE.SCHEMA.FILES
(
[FILENAME] VARCHAR(250)
)
Задача сценария C # для хранения имен файлов:
using System.Data;
using System.Data.SqlClient;
using System.IO;
string currentFile = Dts.Variables["User::FileNameVariable"].Value.ToString();
FileInfo currentFileInfo = new FileInfo(currentFile);
//Integrated Security for Windows authentication
string connectionStr = @"Data Source=Server;Initial Catalog=Database;Integrated Security=SSPI;";
string cmd = @"INSERT INTO DATABASE.SCHEMA.FILES ([FILENAME]) VALUES (@file)";
using (SqlConnection conn = new SqlConnection(connectionStr))
{
using (SqlCommand sql = new SqlCommand(cmd, conn))
{
SqlParameter pFileName = new SqlParameter("@file", SqlDbType.VarChar);
pFileName.Direction = ParameterDirection.Input;
pFileName.Size = 250;
//use FileInfo.Name to get only file path
pFileName.Value = currentFileInfo.Name;
sql.Parameters.Add(pFileName);
conn.Open();
//insert file name
sql.ExecuteNonQuery();
}
}
Задача сценария C # для удаления старых файлов:
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO;
string outputFolder = Dts.Variables["User::OutputFolder"].Value.ToString();
string filePrefix = Dts.Variables["User::FilePrefix"].Value.ToString();
DirectoryInfo di = new DirectoryInfo(outputFolder);
List<string> currentExecutionFiles = new List<string>();
string connectionStr = @"Data Source=Server;Initial Catalog=Database;Integrated Security=SSPI;";
string cmd = @"SELECT [FILENAME] FROM DATABASE.SCHEMA.FILES";
using (SqlConnection conn = new SqlConnection(connectionStr))
{
using (SqlCommand sql = new SqlCommand(cmd, conn))
{
conn.Open();
using (SqlDataReader dr = sql.ExecuteReader())
{
if (dr.HasRows)
{
while (dr.Read())
{
//get file names from table holding names from current execution
currentExecutionFiles.Add(dr[0].ToString());
}
}
}
}
}
foreach (FileInfo fi in di.EnumerateFiles())
{
//check for file with prefix (case insensitive) that was not in current execution
if (fi.Name.StartsWith(filePrefix, StringComparison.InvariantCultureIgnoreCase)
&& !currentExecutionFiles.Contains(fi.Name))
{
fi.Delete();
}
}