Подтвердить что ты не робот

Как преобразовать ErrorCode и ErrorColumn в SSIS в сообщение об ошибке и имя столбца?

Я перенаправляю строки из плоского источника файла в место для плоского файла. Метаданные по умолчанию в перенаправленных строках:

  • Исходная строка источника исходного файла
  • ErrorCode
  • ErrorColumn

То, что я получаю в выходном плоском файле, является исходной строкой (nice) и кодом ошибки (не очень хорошо, например, -1071628249) и столбцом ошибки (не так приятно, поскольку это внутренний идентификатор столбца).

Как преобразовать строки для вывода сообщения об ошибке (например, "Данные были усечены" ) и имя столбца, как определено в файле плоского файла?

Другими словами, вместо ...,-1071607675,10 я хотел бы видеть:

...,The data was truncated,Firstname

или, альтернативно (если предыдущий невозможен);

...,DTS_E_FLATFILESOURCEADAPTERSTATIC_TRUNCATED,Firstname.

4b9b3361

Ответ 1

Часть вопроса (добавление описания ошибки) может быть достигнута с помощью компонента script. Это описано в Улучшение вывода ошибки с помощью script Компонент.

Кажется, что в блоге Dougbert есть решение добавить имя столбца, но это далеко не просто. Я поражен, что это очень сложно сделать в SSIS; вы могли бы подумать, что это была основная потребность знать имя источника и столбца.

Ответ 2

Список сообщений об ошибках находится в следующем расположении: MSDN, Справка об ошибках и сообщениях служб Integration Services http://msdn.microsoft.com/en-us/library/ms345164%28v=sql.100%29.aspx

И Идентификационный номер столбца можно найти в Задаче потока данных SSIS: выберите компонент задачи, который генерирует ошибку, расширенный редактор, вкладку "Свойства ввода и вывода", "Свойства внешних столбцов".

Ответ 3

У Pragmatic Works есть Ошибка вывода Описание Transform, которая является частью Community Edition (бесплатно) продукта, который они называют "Задача Factory".

Сообщение об ошибке Описание Transform предоставляет пользователю пользовательский интерфейс, который может извлекать ценную информацию, такую ​​как ErrorCode, ErrorColumn, ErrorDescription, ComponentName (сгенерированные ошибки), ColumnName (если известно), ColumnType и ColumnLength.

Он также позволяет вам передавать любые входные столбцы в Output Error. Честно говоря, это очень удобно и сэкономило мне время на устранение неполадок в моих пакетах SSIS.

Ответ 4

Существует гораздо более простой ответ. Просто перенаправьте вывод ошибки в новый файл назначения (CSV или что-то еще), а затем включите DataViewer на выходе ошибки....

Data Viewer in SSIS

Ответ 5

Это может быть достигнуто с помощью компонента script в качестве преобразования, вывода ошибки переадресации на компонент script и выполните шаги для достижения того, что вы ищете.

(1) Откройте компонент script,

Входные столбцы выберите

  • ErrorColumn
  • ErrorCode

Ввод и вывод добавить столбцы вывода

  • ErrorDescription (DT_STRING 500)
  • ErrorColumnDescription (DT_STRING 100)

(2) Изменить Script

Вставьте следующий код

    using System;
    using System.Data;
    using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
    using Microsoft.SqlServer.Dts.Runtime.Wrapper;
    #endregion

    /// <summary>
    /// This is the class to which to add your code.  Do not change the name, attributes, or parent
    /// of this class.
    /// </summary>
    [Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
    public class ScriptMain : UserComponent
    {

        public override void Input0_ProcessInputRow(Input0Buffer Row)
        {
            var component130 = this.ComponentMetaData as IDTSComponentMetaData130;
            if (component130 != null)
            {
                Row.ErrorDescription = component130.GetErrorDescription(Row.ErrorCode);
                Row.ErrorColumnDescription = component130.GetIdentificationStringByID(Row.ErrorColumn);
            }
        }

Ответ 6

Вот решение, которое

  • Работает во время выполнения пакета (не предварительно заполняется)
  • Автоматизируется с помощью Script Задачи и компонентов
  • Не требует установки новых сборок или настраиваемых компонентов
  • Совместимо с BIML

Посмотрите здесь полное решение.


Вот короткая версия.

  • Создать 2 переменных объекта, execsObj и lineageIds
  • Создайте Script Задачу в потоке управления, дайте ей доступ ReadWrite к обеим переменным
  • Вставьте следующий код в задачу Script
Dictionary<int, string> lineageIds = null;

public void Main()
{
    // Grab the executables so we have to something to iterate over, and initialize our lineageIDs list
    // Why the executables?  Well, SSIS won't let us store a reference to the Package itself...
    Dts.Variables["User::execsObj"].Value = ((Package)Dts.Variables["User::execsObj"].Parent).Executables;
    Dts.Variables["User::lineageIds"].Value = new Dictionary<int, string>();
    lineageIds = (Dictionary<int, string>)Dts.Variables["User::lineageIds"].Value;
    Executables execs = (Executables)Dts.Variables["User::execsObj"].Value;

    ReadExecutables(execs);

    Dts.TaskResult = (int)ScriptResults.Success;
}

private void ReadExecutables(Executables executables)
{
    foreach (Executable pkgExecutable in executables)
    {
        if (object.ReferenceEquals(pkgExecutable.GetType(), typeof(Microsoft.SqlServer.Dts.Runtime.TaskHost)))
        {
            TaskHost pkgExecTaskHost = (TaskHost)pkgExecutable;
            if (pkgExecTaskHost.CreationName.StartsWith("SSIS.Pipeline"))
            {
                ProcessDataFlowTask(pkgExecTaskHost);
            }
        }
        else if (object.ReferenceEquals(pkgExecutable.GetType(), typeof(Microsoft.SqlServer.Dts.Runtime.ForEachLoop)))
        {
            // Recurse into FELCs
            ReadExecutables(((ForEachLoop)pkgExecutable).Executables);
        }
    }
}

private void ProcessDataFlowTask(TaskHost currentDataFlowTask)
{
    MainPipe currentDataFlow = (MainPipe)currentDataFlowTask.InnerObject;
    foreach (IDTSComponentMetaData100 currentComponent in currentDataFlow.ComponentMetaDataCollection)
    {
        // Get the inputs in the component.
        foreach (IDTSInput100 currentInput in currentComponent.InputCollection)
            foreach (IDTSInputColumn100 currentInputColumn in currentInput.InputColumnCollection)
                lineageIds.Add(currentInputColumn.ID, currentInputColumn.Name);

        // Get the outputs in the component.
        foreach (IDTSOutput100 currentOutput in currentComponent.OutputCollection)
            foreach (IDTSOutputColumn100 currentoutputColumn in currentOutput.OutputColumnCollection)
                lineageIds.Add(currentoutputColumn.ID, currentoutputColumn.Name);
    }
}

4. Создайте Script компонент в потоке данных с доступом ReadOnly к lineageIds и следующему коду.

public override void Input0_ProcessInputRow(Input0Buffer Row)
  {
      Dictionary<int, string> lineageIds = (Dictionary<int, string>)Variables.lineageIds;

      int? colNum = Row.ErrorColumn;
      if (colNum.HasValue && (lineageIds != null))
      {
          if (lineageIds.ContainsKey(colNum.Value))
              Row.ErrorColumnName = lineageIds[colNum.Value];

          else
              Row.ErrorColumnName = "Row error";
      }
      Row.ErrorDescription = this.ComponentMetaData.GetErrorDescription(Row.ErrorCode);
  }

Ответ 7

    //column error description 
    Row.ErrorDescription = this.ComponentMetaData.GetErrorDescription(Row.ErrorCode);

    //we are getting column name with some extra information
    String rawColumnName = this.ComponentMetaData.GetIdentificationStringByLineageID(Row.ErrorColumn);

    //extracting positions of brackets 
    int bracketPos = rawColumnName.LastIndexOf('[')+1;
    int lastBracketPos = rawColumnName.LastIndexOf(']');

    //extracting column name from the raw column name
    Row.ErrorColName = rawColumnName.Substring(bracketPos, (lastBracketPos - bracketPos));