Why Script Component

Script Component使我们具有在SSIS中使用.net自定义代码的功能,我们可以使用它达到以下的目的,或者说在ETL中有如下需要的时候我们应该考虑使用ScriptComponent

  1. 如果我们需要对数据做多重转换(比如在两个列上分别加上值然后求平均等),我们可以使用ScriptComponent而不是在数据流中使用多个转换空间

  2. 访问一些已经存在于.net程序及中的业务规则

  3. 使用以下自定义的公式或函数,比如使用银行卡校验算法(Luhn)来验证信用卡号

  4. 校验列数据并且略过不恰当的数据,比如检查年龄列并且略过所有年龄大于100或小于0岁的数据

我们看到Script Component提供了一种方式,使我们以.net编程的方法在数据流中添加自定义的数据处理功能,不过如果我们的目标是在多个Package中重用该自定义功能的话,应该考虑开发自定义的模块而不是使用脚本模块。

使用ScriptComponent

Script Component可以被用作SourceTransformationDestination,取决于它的用途,它可以支持一个Input以及多个Output。该控件中的自定义Script会被InputOutput中的每一行都触发一次:

  1. 如果被用作Source,它支持多个Output

  2. 如果被用作Transformation,它支持一个输入及多个输出

  3. 如果被用作Destination,它支持一个输入

  4. 不支持错误输出

 

如果简单来将,Script Component的使用其实只需要简单的两步:在设计器中配置元数据及在VSTA中编辑脚本。

配置元数据

相比于其他模块,Script Component只有简单的4个界面:

Script界面

脚本界面中最主要的其实就是变量的配置,我们可以选择一些只读以及一些可读可写的变量传给脚本,然后脚本中可以使用这些变量来作为输入或输入值:

wKioL1Q2QrCh64hPAABLzWO0GPY108.jpg

Input界面

该界面只有Script Component被用作TransformationDestination的时候有。它跟其他模块的Input没什么区别,都是选择一些从某个输入过来的列而已:

wKiom1Q2QpTCY-U1AAE0TPOBEsU262.jpg

InputOutput界面

该界面最主要的是可以添加自定义的OutputOutput列,并指定列的数据类型:

wKiom1Q2QqvSSIAYAAHKrpwn2JY749.jpg

Connection Manager界面

这里可以添加脚本中会使用的连接管理器,不过在实际项目中我从来没用过该界面。

脚本编辑

脚本编辑界面通过在Script界面点击编辑脚本进入,在讨论如何自定义我们的代码之前我们先看一下自定义代码的骨架。如下所示,其实主要有三个文件两个类:

wKiom1Q2Qr3zv6TuAAA578riIe8488.jpg

其中ComponentWrapper文件表示一个自定义的Script Component模块类 -UserComponent,它继承自ScriptComponent基类。下面是该类的一个简单视图,它主要包含了两类东西:一是ConnectionsVariables变量,我们可以用它们来获取ScriptComponent模块元数据设计器中指定的ETL变量和连接管理器;另一类是一些可重写的函数(截图中未列出)以允许我们可以重写来处理输入和输出。

wKioL1Q2QwTBXIwdAACPQf_52bM065.jpg

BufferWrapper文件表示控件的缓冲部分,我们知道对任何的数据流任务都是需要用到缓冲的:

wKiom1Q2Qt2DZ_YxAADc9aqzXyU538.jpg

最后main文件中包含的类才是真正的ScriptComponent入口类,它名为ScriptMain并继承自UserComponent,表示我们创建的该ScriptComponent控件:

wKioL1Q2QybD_EG8AADsa7lXQuM200.jpg

用作Source

Script Component用作Source的时候,因为只有输出没有输入,所以main文件中的ScriptMain类会包含一个名为CreateNewOutputRows()的函数,我们所有需要处理及输出的内容都在直接或间接放在这个函数中,如果刨除其他自定义的逻辑,该函数的功能其实只有两个:

  1. 在输出缓冲中新加一行数据,这通过调用MyOutputName.AddRow()函数来实现,其中MyOutputName就是我们在元数据设计器中建的输出流的名字

  2. 为新加的这行数据的各个列赋值,者通过MyOutputName.ColumnName= val来实现

wKiom1Q2SBmC7M0UAACkFh8LxNA747.jpg

用作Transformation

当用作转换的时候,我看MSDN上说可以有多个输出,但是在实际的代码中发现并不能实现这一点,不知道是不是我弄错了。现在看到的情形是,对于用作转换和目的地的情况,ScriptMain函数有一个InputName_ProcessInputRow()函数,该函数的如参是输入缓冲中的数据行,但是你同样能找到你在自定义输出中的列并为其赋值。比如下面的例子中,Name列是输入列,outputName列是输出列,它们都可以在Input0Buffer中找到。所以对于这种情况下的脚本控件,其主要的两步功能是用同一种方式实现的:

  1. 获取输入的值,通过Row.ColName获取

  2. 为输出列赋值,通过Row.outputCol赋值

wKioL1Q2SGKha-rKAADDaww-rsQ331.jpg