В настоящее время я экспериментирую с использованием переменных SSIS для передачи объектов синхронизации из одного компонента сценария в другой. Это довольно громоздко, но вы можете эффективно использовать несколько компонентов сценария для приема различных входных данных, а затем использовать классы System.Threading для синхронизации передача значений из одного компонента скрипта в другой.
Препятствие заключается в том, что каждый сценарий находится в своем собственном пространстве имен и не может использовать классы совместно с другими сценариями (если только вы не хотите компилировать и развертывать свою собственную сборку с помощью SSIS). В данный момент я передаю (через общую переменную) ссылку на объект [], содержащую ссылку на 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: - Если у вас есть время и энергия, то написание подходящего настраиваемого компонента SSIS действительно является подходом для сценариев с несколькими входами.