具有多个输入的SSIS脚本组件

时间:2009-04-22 12:22:56

标签: ssis

我正在寻找一种在SSIS中创建可接受多个输入的脚本组件的方法。

我需要这个,所以我可以做一种自定义加入的形式。

一个脚本可以有多个输出而只有一个输入似乎很愚蠢,我敢肯定我一定做错了。

任何帮助?

2 个答案:

答案 0 :(得分:1)

尝试在您的脚本组件之前放置一个Union All组件,而不是让列匹配,将列添加到输出中,以便每个元素都在一个唯一的列中结束。

请记住,首先SSIS脚本组件将逐行处理项目,因此需要使用某些集合完成自定义连接机制,并捕获在处理完所有行后触发的事件。

请记住,我假设您在数据流中使用的是脚本组件,而不是控制流,我假设您正在使用SSIS 2005。

答案 1 :(得分:0)

我目前正在尝试使用SSIS变量从一个脚本组件或另一个脚本组件传递同步对象。它相当笨拙,但您可以有效地使用多个脚本组件来接受各种输入,然后使用System.Threading类来同步将值从一个脚本组件传递到另一个脚本组件。

障碍是每个脚本都在它自己的命名空间中,不能与其他脚本共享类(除非你想用SSIS编译和部署你自己的程序集)。我目前正在做的是传递(通过共享变量)对object []的引用,包含对ManualResetEvent,SSIS PipelineBuffer和管道列索引数组的引用。

这足以让接收脚本重建另一个脚本的输入管道,将其抽干,然后发出信号告知它已完成。

它的功能,虽然我正在寻找解决这个事实(似乎)SSIS在脚本组件的生命周期内两次调用“ProcessInput”的事实。如果SO上的任何天才都有解决方案,那么我认为我们已经有了一个[clumsey]解决方案来允许多个输入到单个脚本组件。

任何参赛者?

----编辑----

我已经启动并运行了 - 这个技巧是使用同步来防止ProcessInput的多线程调用尝试多次共享输入缓冲区。下面是我如何工作的粗略代码示例:

脚本组件1:分享它的输入......

using System;
using System.Collections;
using System.Threading;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using Microsoft.SqlServer.Dts.Pipeline;

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{


    System.Collections.Generic.List<object> shared = null;
    System.Threading.ManualResetEvent sync;

    public override void ProcessInput(int InputID, PipelineBuffer Buffer)
    {
        lock (this)
        {
            if (InputID == 82)
            {
                if (shared == null)
                {
                    shared = new System.Collections.Generic.List<object>();
                    sync = new System.Threading.ManualResetEvent(false);
                    shared.Add(sync);
                    shared.Add(Buffer);
                    shared.Add(GetColumnIndexes(InputID));

                    IDTSVariables100 vars = null;

                    this.VariableDispenser.LockOneForWrite("Test", ref vars);

                    vars[0].Value = shared;
                    vars.Unlock();
                    sync.WaitOne();
                    System.Windows.Forms.MessageBox.Show("Done");
                }
            }
        }
    }
}

...然后脚本组件2(使用脚本组件1的输入)...

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

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
    System.Threading.ManualResetEvent sync = null;
    InputXBuffer sharedBuffer = null;

    public override void Input0_ProcessInput(Input0Buffer Buffer)
    {
        lock (this)                 // Only 1 thread at a time
        {
            if (sharedBuffer == null)
            {
                object Test = null;
                while (Test == null)
                {
                    System.Threading.Thread.Sleep(100);
                    IDTSVariables100 vars = null;
                    this.VariableDispenser.LockOneForRead("Test", ref vars);
                    Test = vars[0].Value;
                    vars.Unlock();
                }

                var sharedList = Test as System.Collections.Generic.List<object>;

                if (sharedList != null)
                {
                    sync = sharedList[0] as System.Threading.ManualResetEvent;
                    var buffer = sharedList[1] as PipelineBuffer;
                    var bufferColumnIndexes = sharedList[2] as int[];
                    sharedBuffer = new InputXBuffer(buffer, bufferColumnIndexes);
                }
            }
       }

        while (sharedBuffer.NextRow())
        {
            // ... do stuff with Script Component 1's shared input here...
        }
        sync.Set();     // Signal script 1 that we're done
    }
}

脚本共享一个名为“Test”的读/写变量 - 您可以更改变量名以满足您的需求。正如上面所说的那样,你可以将它提升到一个新的水平。

PS: - 如果你有时间&amp;能量,编写适当的自定义SSIS组件确实是多输入场景的方法。