Как получить имя папки и ошибку имени файла в SSIS при использовании цикла foreach - PullRequest
0 голосов
/ 23 января 2019

Я использую SSIS для вставки данных в базу данных.Я использую цикл foreach для зацикливания папки и файлов в этой папке.Я хочу получить имя папки и имя файла с ошибкой в ​​процессе.И я буду регистрировать их в текстовом файле.Все, помогите мне, спасибо!

1 Ответ

0 голосов
/ 23 января 2019

Обзор этого ниже.Некоторые вещи могут различаться в зависимости от вашей среды и того, как вы хотите регистрировать имена папок и файлов, в которых были ошибки, но это должно помочь вам начать работу в правильном направлении.

  • СозданиеПеременная int, вы можете вызвать это «ErrorCount» и убедиться, что его значение установлено равным 0. Это будет использовано позже в журнале ошибок.

  • Создайте задачу «Выполнение SQL», которая создасттаблица, которая будет использоваться для хранения папки и имени файла.«Имя файла» - это ключевое слово в T-SQL, поэтому используются идентификаторы (квадратные скобки).Они не обязательны, но облегчают чтение.

  • Поскольку вы уже используете цикл Foreach для загрузки файлов, я предполагаю, что переменная уже сопоставлена ​​для хранения файлаимя для каждой итерации.Если вы этого не сделали, добавьте строковую переменную с индексом 0 на панели «Переменные переменные» цикла Foreach.
  • В задаче потока данных, загружающей файлы, добавьте обработчик событий OnErrorс задачей скрипта C #.В редакторе задач сценария добавьте строковую переменную, содержащую имя файла (индекс 0 в цикле Foreach) в поле ReadOnlyVariables.В поле ReadWriteVariables добавьте созданную ранее переменную «ErrorCount» и системную переменную System::Propagate.Это будет использовано позже, чтобы разрешить обработку последующих файлов после ошибки.

  • Код для этой задачи сценария приведен ниже в этом посте.Вам нужно будет добавить ссылки на пространства имен System.IO и System.Data.SqlClient.Событие OnError запускается один раз для каждой ошибки , а не только тогда, когда был файл с ошибкой.В этом примере имя файла регистрируется только в том случае, если пользовательская переменная «ErrorCount» имеет значение 0. После того, как файл и папка зарегистрированы, эта переменная устанавливается в 1, чтобы избежать одновременной регистрации одного и того же файла несколько раз.Методы Path.GetDirectoryName и Path.GetFileName используются для получения имен папок и файлов соответственно.Хотя все загружаемые вами файлы, скорее всего, имеют одинаковое расширение, Path.GetFileName по-прежнему используется для возврата расширения файла с именем файла.Если вы не хотите видеть расширение файла, используйте метод Path.GetFileNameWithoutExtension.

  • SSPI установлено для встроенной безопасности, чтобы указать, что будет использоваться аутентификация Windows.Чтобы использовать проверку подлинности SQL Server, установите для нее значение false и добавьте соответствующие значения для свойств User ID и Password.Я бы рекомендовал использовать параметры, то есть объекты SqlParameter ниже, вместо того, чтобы создавать команду SQL в виде объединенной строки.Ввод по умолчанию ParameterDirection, но они все еще определены для ясности.Этот сценарий берет проанализированные имена папок и файлов и вставляет их в таблицу, в данном примере с именем ErrorFiles, которая будет использоваться для хранения файлов, в которых возникли ошибки во время выполнения пакета, до их записи в файл.Хотя вставка с помощью задачи «Выполнение SQL» будет проще, методы в пространстве имен System.IO позволяют корректно получить имя папки и файла при изменении пути к файлу.Если используемая папка никогда не изменяется, можно выполнить задачу «Выполнение SQL» с функцией T-SQL SUBSTRING во вставке, чтобы проанализировать имя папки и файла из переменной, в которой они хранятся.

  • После задачи потока данных добавьте еще одну задачу сценария в цикл по каждому элементу.Подключите это к Задаче потока данных и измените операцию оценки для Ограничение приоритета на Выражение и добавьте выражение ниже.Это обеспечит выполнение следующей задачи сценария только в том случае, если во время этой итерации цикла Foreach произошла ошибка, путем проверки значения переменной «ErrorCount».

  • В этой задаче сценариядобавьте «ErrorCount» в поле ReadWriteVariables и аналогично установке этого значения в 1 ранее, теперь установите его обратно в 0 (Dts.Variables["User::ErrorCount"].Value = 0).Это делается для того, чтобы файлы, которые приводят к ошибке в последующих итерациях цикла Foreach, также регистрировались.

  • После цикла по каждому элементу добавьте задачу потока данных с источником OLE DB.Установите для режима доступа к данным команду SQL и выберите столбцы FolderName и FileName из таблицы, в которой хранятся файлы с ошибками.Если вы не создали эту таблицу отдельно, вы можете установить для ValidateExternalMetadata значение false и добавить выходные столбцы в папку «Внешние и выходные столбцы» на вкладке «Свойства ввода и вывода» в расширенном редакторе.Однако, если вы не знакомы с этим, может быть проще просто запустить CREATE TABLE DDL и определить метаданные таким образом.В этой задаче потока данных добавьте пункт назначения плоского файла, который подключен к источнику OLE DB.Создайте новый диспетчер плоских файлов с именем файла, который вы хотите использовать для хранения имен файлов, содержащих ошибки.Вы можете захотеть использовать выражение в имени файла, чтобы сделать его уникальным при каждом выполнении пакета.Пример выражения приведен ниже в этом посте.Это просто использует текущую дату.Если вы планируете запускать это несколько раз в течение одного дня, вы можете добавить временную метку или иным образом сделать каждое имя файла уникальным.Это можно установить в качестве имени выходного файла, добавив это выражение в переменную и используя его в качестве свойства ConnectionString диспетчера плоских файлов.

  • Затем добавьте Execute SQLЗадача, следующая за этой задачей потока данных.Для SQLStatement добавьте SQL, чтобы удалить таблицу, в которой хранятся имена файлов с ошибками, если таковые существуют.Хотя в этом нет необходимости, поскольку первоначальная задача, которая создает эту таблицу, удаляет ее, это позволяет избежать наличия дополнительной таблицы в вашей базе данных.

Выражение ограничения предшествования:

@[User::ErrorCount] > 0

Выражение строки подключения диспетчера соединений с плоскими файлами:

"C:\\Your Folder\\" + (DT_STR, 4, 1252)DATEPART("Year", GETDATE()) + "_"
 + (DT_STR, 2, 1252)DATEPART("Month", GETDATE()) + "_" 
 + (DT_STR, 2, 1252)DATEPART("Day", GETDATE()) +"_"
+ "ErrorFiles.txt"

Таблица файлов ошибок DDL:

IF(OBJECT_ID(N'YourDatabase.DBO.ERRORFILES') IS NOT NULL)
BEGIN
DROP TABLE YourDatabase.DBO.ERRORFILES
END

CREATE TABLE YourDatabase.DBO.ERRORFILES 
(
FOLDERNAME VARCHAR(100),
[FILENAME] VARCHAR(100)
)

Код задачи сценария обработчика события OnError:

 if (Convert.ToInt32(Dts.Variables["User::ErrorCount"].Value.ToString()) == 0)
{
    string connString = @"Data Source=YourSQLServerInstance;Initial Catalog=YourDatabase;Integrated Security=SSPI";

    string cmd = @"Insert into dbo.ErrorFiles (FolderName,[FileName]) values (@folderName, @fileName)";

    //parse variable with file that caused error
    string errorFileFullName = Dts.Variables["User::NameForTable"].Value.ToString();

    //get folder
    string errorFolderName = Path.GetDirectoryName(errorFileFullName);
    //get only file name
    string errorFileName = Path.GetFileName(errorFileFullName);

    using (SqlConnection conn = new SqlConnection(connString))
    {
        SqlCommand sql = new SqlCommand(cmd, conn);

        SqlParameter pFolderName = new SqlParameter("@folderName", SqlDbType.VarChar);
        pFolderName.Direction = ParameterDirection.Input;
        pFolderName.Value = errorFolderName;
        pFolderName.Size = 100;

        SqlParameter pFileName = new SqlParameter("@fileName", SqlDbType.VarChar);
        pFileName.Direction = ParameterDirection.Input;
        pFileName.Value = errorFileName;
        pFileName.Size = 100;

        sql.Parameters.Add(pFolderName);
        sql.Parameters.Add(pFileName);

        conn.Open();

        sql.ExecuteNonQuery();

        //avoid failing Foreach Loop so other files are processed
        Dts.Variables["System::Propagate"].Value = false;

        //prevent event handler from firing multiple times. 
        Dts.Variables["User::ErrorCount"].Value = 1;

    }
}
...