首页 > 解决方案 > SSIS 读取一个 System.Object 变量并在脚本组件中写入它......如何?

问题描述

我有一个 SSIS 包,它以一个脚本任务开始,它初始化一个空的 DataTable 并将其分配给一个用户变量。我正在添加一些示例行,因为我仍在进行开发。该变量FlatFileBadRowDataTracker在 SSIS中称为:

public void Main()
{
    // TODO: Add your code here
    string SSISRunStartTimeStamp = DateTime.Now.ToString("yyyyMMddHHmmss");
    Dts.Variables["User::SSISRunStartTimeStamp"].Value = SSISRunStartTimeStamp;
    Dts.Variables["User::FlatFileBadRowDataTracker"].Value = BuildSampleDataTable();


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

private DataTable BuildSampleDataTable()
{
    DataTable dt = new DataTable();

    // ErrorColumn
    DataColumn errorColumn = new DataColumn("ErrorColumn");
    errorColumn.DataType = System.Type.GetType("System.String");
    errorColumn.DefaultValue = string.Empty;
    dt.Columns.Add(errorColumn);

    // ErrorDescription
    DataColumn errorDescription = new DataColumn("ErrorDescription");
    errorColumn.DataType = System.Type.GetType("System.String");
    errorColumn.DefaultValue = string.Empty;
    dt.Columns.Add(errorDescription);

    // FileName
    DataColumn fileName = new DataColumn("FileName");
    errorColumn.DataType = System.Type.GetType("System.String");
    errorColumn.DefaultValue = string.Empty;
    dt.Columns.Add(fileName);

    // RawData
    DataColumn rawData = new DataColumn("RawData");
    errorColumn.DataType = System.Type.GetType("System.String");
    errorColumn.DefaultValue = string.Empty;
    dt.Columns.Add(rawData);

    // ErrorDescription
    DataColumn dataFlowComponent = new DataColumn("DataFlowComponent");
    errorColumn.DataType = System.Type.GetType("System.String");
    errorColumn.DefaultValue = string.Empty;
    dt.Columns.Add(dataFlowComponent);

    // Populate with some sample data.
    DataRow row;
    for (int i = 1; i < 5; i++)
    {
        row = dt.NewRow();
        row["ErrorColumn"] = "ErrorColumn" + i;
        row["ErrorDescription"] = "ErrorDescription" + i;
        row["FileName"] = "FileName" + i;
        row["RawData"] = "RawData" + i;
        row["DataFlowComponent"] = "SSIS_DataFlowTask_" + i;
        dt.Rows.Add(row);
    }

    return dt;
}

#region ScriptResults declaration
/// <summary>
/// This enum provides a convenient shorthand within the scope of this class for setting the
/// result of the script.
/// 
/// This code was generated automatically.
/// </summary>
enum ScriptResults
{
    Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
    Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
#endregion

然后我有一个数据流任务,它读取一个文本文件(通过平面文件源组件的 csv)并有一个脚本组件(作为转换)来确定行是好还是坏。好的行被发送到脚本组件的“GoodRow”输出,而坏的行被发送到“BadRows”输出。通常一个文件会有大部分是好的行,但少数会有数据错误(例如:email 列有一些不像电子邮件地址的东西),在这种情况下,组件必须将其发送到 BadRows 输出。我的目标是将错误相关数据(例如具有数据错误的列名和一些描述)捕获到我之前在脚本任务中创建的同一个 DataTable 中。

我在脚本组件编辑器屏幕的属性下的ReadWriteVariables中添加了这个变量。我在 中使用它PreExecute()来获取 DataTable 的架构并将其分配给dt我在类开头声明的局部变量。

public override void PreExecute()
{
    base.PreExecute();
    dt = (DataTable)Variables.FlatFileBadRowDataTracker;

} 

然后dt,当我在方法中发现与数据相关的错误时,我尝试将数据添加到Input0_ProcessInputRow(Input0Buffer Row)其中。之后,PostExecute()我尝试将其分配dt回用户变量。

public override void PostExecute()
{
    base.PostExecute();
    Variables.FlatFileBadRowDataTracker = dt;
}

但是,当我运行包时,我收到此错误(如下所示),它告诉我无法在 PreExecute() 方法中使用该变量。看来我只能在 PostExecute() 方法中使用它。我需要数据表的现有数据+模式,否则我将不得不重新创建模式并且我会丢失数据(现在它只是代码中显示的测试数据)。

在此处输入图像描述

有什么方法可以在我的脚本组件中获取 DataTable 的模式+数据?脚本组件也不允许我在ReadOnlyVariables和中添加变量ReadWriteVariables。看来我只能将它添加到其中一个。

标签: c#sql-serverssisetlscript-component

解决方案


尝试使用变量分配器而不是选择变量作为读写变量:

预执行阶段:

IDTSVariables100 vars = null;
VariableDispenser.LockForRead("User::FlatFileBadRowDataTracker");
VariableDispenser.GetVariables(out vars);
dt = (DataTable)vars["User::FlatFileBadRowDataTracker"].Value;
vars.Unlock();

执行后阶段:

IDTSVariables100 vars = null;
VariableDispenser.LockForWrite("User::FlatFileBadRowDataTracker");
VariableDispenser.GetVariables(out vars);
vars["User::FlatFileBadRowDataTracker"].Value = dt;
vars.Unlock();

有关其他信息,请参阅:


推荐阅读