Как объявить переменную C #, которая возвращает нарезанную строку другой переменной в моем пакете служб SSIS? - PullRequest
0 голосов
/ 27 апреля 2019

Я создаю пакет для передачи файлов, который копирует файлы в выходную папку, а затем копирует их в отдельный архив.Файлы часто заменяются новыми файлами с форматом имени файла, таким как xxxx20190427.zip. Я создал цикл foreach в SSIS для копирования / перемещения файлов, но не могу понять, как заменить старые версии.Когда я перемещаю файлы в выходную папку, я хочу заменить файл из предыдущей загрузки.Я пытаюсь создать задачу скрипта, которая создает переменную, основанную на подстроке переменной, объявленной в цикле foreach, чтобы при наличии файла xxxx20190427.zip он проверял наличие части «xxxx» в именах файлов моего выводапапку и удаляет этот файл, если он присутствует, так что доступен только самый новый файл.

1 Ответ

0 голосов
/ 29 апреля 2019

Ниже приведен обзор процесса с парой задач скрипта 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();
    }
}
...