我正在寻找一种在SSIS中创建可接受多个输入的脚本组件的方法。
我需要这个,所以我可以做一种自定义加入的形式。
一个脚本可以有多个输出而只有一个输入似乎很愚蠢,我敢肯定我一定做错了。
任何帮助?
答案 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组件确实是多输入场景的方法。