在DataFlow脚本组件中将RecordSet枚举为数据源

5

这是一个与SSIS相关的问题

我有一个变量,类型为object。一个数据流将一些筛选后的行导入到记录集中,并将该记录集存储在对象变量中。

在完全分离的另一个数据流中,我需要将该记录集用作源。因此,我创建了一个脚本组件,并告诉它它将是一个数据源。

我设置了三个输出列,我需要它们。我的问题是,如何让记录集中的每一行都在脚本组件中创建一个新行?

我将记录集变量作为只读变量传递进去,当我尝试foreach变量以获取每一行时,我无法这样做,因为该变量没有定义get enumerator方法。

因此,我无法将每一行打印到那些列中,也无法将我的脚本组件用作数据源。

是否有其他人遇到过类似的情况?我是否做了什么愚蠢的事情,或者您是以另一种替代方式完成的?

作为说明,我在脚本中使用C#和Visual Studio 2008


你是否使用了 ADO ForEach 枚举对象? - praveen
3个回答

7

我在周围搜索了一下,找到了一个VB解决方案来解决我的问题,然后我将其翻译成了C#,现在已经可以编译并正常运行了。我使用的代码如下:

    DataTable datatable = new DataTable();
    System.Data.OleDb.OleDbDataAdapter oAdapter = new System.Data.OleDb.OleDbDataAdapter();

    oAdapter.Fill(datatable,ReadOnlyVariables["User::XXXXX"]);

    foreach (DataRow row in datatable.Rows)
    {
        Output0Buffer.AddRow();
        Output0Buffer.CoverAmount = Convert.ToInt32(row["XXXX"].ToString());
    } 

对于其他遇到类似问题的人!

感谢所有提供帮助的人


4

我做了类似的事情,基于Andy Leonard的增量加载框架的旧版本。我们的子包填充一个记录集,指示我们有多少新的、改变的、不变的等行数。在父包中,我们测试该对象以确保在使用它之前已经填充。我需要赶去开会,所以请原谅这段代码,因为它并没有完全解决你的具体需求,但希望能为你提供正确方向上的坚实推动,直到我回来并为你量身定制。我在那里放了伪代码,告诉你何时做什么。

    public void Main()
    {
        bool debug = Convert.ToBoolean(Dts.Variables["Debug"].Value);
        string taskName = string.Empty;
        string packageName = string.Empty;
        string sourceName = string.Empty;
        bool fireAgain = false;

        taskName = Convert.ToString(Dts.Variables["TaskName"].Value);
        packageName = Convert.ToString(Dts.Variables["PackageName"].Value);
        // Fix this by defining and passing in params
        sourceName = Convert.ToString(Dts.Variables["TaskName"].Value);

        System.Data.OleDb.OleDbDataAdapter adapater = null;
        System.Data.DataTable table = null;
        System.Data.DataColumn column = null;
        System.Data.DataRow row = null;
        string message = string.Empty;

        object rowCounts = null;
        rowCounts = Dts.Variables["RowCounts"].Value;
        table = new DataTable();

        try
        {
            // Get us out of this crazy thing - should only be an issue
            // first pass through
            if (rowCounts == null)
            {
                Dts.TaskResult = (int)ScriptResults.Success;
                return;
            }
        }
        catch (Exception ex)
        {
            throw new Exception("Failed here");
        }

        adapater = new System.Data.OleDb.OleDbDataAdapter();
        try
        {
            // This works if we pass in a dataset
            //adapater.Fill(table, Dts.Variables["RowCounts"].Value);
            adapater.Fill(table, rowCounts);
            // TODO: Enumerate through adapter
            // Call Output0Buffer.AddRow();
            // and Output0Buffer.MyColumn.Value = adapter[i].value // possibly casting to strong type
        }
        catch (Exception ex)
        {
            try
            {
                // This works if we use a datatable
                System.Data.DataSet ds = null;
                //ds = (DataSet)Dts.Variables["RowCounts"].Value;
                ds = (DataSet)rowCounts;
                table = ds.Tables[0];
                // TODO: Enumerate through datatable as we do with adapter

            }
            catch (Exception innerException)
            {
                // continue to swallow exceptions
            }
            Dts.Variables["ValidCounts"].Value = false;

            // trap "Object is not an ADODB.RecordSet or an ADODB.Record
            // parse ex.Message
            if (ex.Message.Contains("System.ArgumentException: "))
            {
                System.Text.StringBuilder exceptionMessage = null;
                exceptionMessage = new System.Text.StringBuilder();
                exceptionMessage.Append(ex.Message);
                exceptionMessage.Replace("\nParameter name: adodb", string.Empty);
                exceptionMessage.Replace("System.ArgumentException: ", string.Empty);

                if (exceptionMessage.ToString() != "Object is not an ADODB.RecordSet")
                {
                    Dts.Events.FireInformation(0, string.Format("{0}.{1}", packageName, taskName), exceptionMessage.ToString(), string.Empty, 0, ref fireAgain);
                }
            }
        }

        Dts.Variables["ValidCounts"].Value = false;
        if (table.Rows.Count > 0)
        {
            Dts.Variables["ValidCounts"].Value = true;
        }

        if (debug)
        {
            message = string.Format("SourceName:  {0}\nValidCounts:  {1}", sourceName, false);
            //System.Windows.Forms.MessageBox msgBox = null;
            //msgBox = new MessageBox();
            System.Windows.Forms.MessageBox.Show(message, string.Format("{0}.{1}", packageName, taskName));
            //MessageBox(message, string.Format("{0}.{1}", packageName, taskName));
        }

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

0
我正在处理与 OP 相同的问题。在我的情况下,我假设它是一个对象,并花了很多时间尝试将其转换为数据表。但我发现这个对象已经是一个数据表了,所以我可以从 SSIS 脚本任务组件中编写以下代码:
DataTable dt = (DataTable)ReadOnlyVariables["User::FTP_DataPath_File_Metadata"].Value;

foreach (DataRow row in dt.Rows)
{
    CustomOutputBuffer.AddRow();
    CustomOutputBuffer.FileName = row.ItemArray[0].ToString();
    CustomOutputBuffer.FileLastModified = Convert.ToDateTime(row.ItemArray[1]);
    CustomOutputBuffer.FileSize = Convert.ToInt32(row.ItemArray[2]);
}

使用脚本组件作为源,成功将我的“对象变量”转换为数据流。

此示例是为了适应Task Factory Secure FTP组件而制作的,该组件将“获取带有元数据的文件列表”的结果保存到对象变量中。


这给了我一个错误,即“无法将类型为'System.__ComObject'的COM对象强制转换为类类型'System.Data.DataTable.'” - codeMonkey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接