微软BI 之SSIS 系列 - 使用 Script Component Transformation 异步转换不规则文件

浏览: 3610

开篇介绍

在数据流中, Script Component 中的 Transformation 类型不仅可以实现同步转换功能,并且还可以实现异步转换功能。所谓同步转换,即在从上游数据行传递给 Script Component 的时候,是每传入一行处理一行再往下输出一行。异步转换一般是需要接受到来自上游的所有行,处理之后再往下输出。但是,异步转换也分为完全阻塞和非完全阻塞,对于异步转换控件比如 Sort, Aggregate 就是异步的完全阻塞转换控件。而 Script Component 异步 Transformation 是一个半阻塞的转换组件,也接受一部分数据的同时,可能也会向下输出一部分(这取决于它自身的内部实现,我们无法深入了解深层次的设计),这时可以通过观察得出来的结论。

 

下面用 Script Component 异步转换 (Asynchrounous Transformation) 来演示如何处理一个不规则的文件的。

Script Component - Transformation, Asynchrounous

跟上一篇文章的数据源一样,也是将不规则的文件正行数据当作一个列来使用。

还是拖放一个 Script Component,类型选择 Transformation 转换。

编辑 Script Component,Input 输入还是 EMPLOYEE。

两个 Output 输出的配置和上一篇文章还是一样的,唯一的区别就是这里的两个 Output 都是异步的,因为不绑定到任何一个 Input。

回到 Script 代码部分,通过简单的 Message 观察一下各默认方法调用和执行的顺序。

第一个还是和之前几篇文章提到的一样,仍然是 PreExecute() 方法被调用。

这个方法可以用来创建 Output 输出。

中间有多少行这个方法就会被调用多少次。

最后一个是 PostExecute() 方法的调用,但是由于行数太多就不等待截图了,直接结束演示。

 

仅仅是这样,我们可以从上面看到数据流在经过 Script Component 的时候仍然是以行为单位执行并往下输出的,ProcessInputRow() 是用来处理行的。

在代码中加入一个方法,很明显是一个重写的方法。注意到这里是 ProcessInput,参数仍然是一样的类型:

 public override void Input0_ProcessInput(Input0Buffer Buffer)
{
MessageBox.Show(
"Input0_ProcessInput()");
}

再次执行包的时候,PreExecute() 仍然是第一个执行,并且只会执行一次。

这个方法也被调用到了。

新写入的方法被调用的同时,注意看这里的方法,ProcessInput() 方法被调用的时候,这时 293 行数据全部进入到 Script Component 中。(在当前代码中,这个方法被调用了两次)

并且紧接着 PostExecute() 方法被调用了,表示数据流处理结束了,但要注意到 Process Input Row() 方法此时并未被调用到。

首先要理解一下 Input0_ProcessInput(Input0Buffer Buffer) 方法,这个方法被执行的时候实际上 Input 输入源中所有的数据行就已经进入到 Script Component 中了。并且当我们在脚本中显示的重写这个方法的时候,Input0_ProcessInputRow(Input0Buffer Row) 将不再被执行。并且从参数命名上来看,前者是 Buffer,后者是 Row 尽管类型是一致的,但是实则在参数命名上就已经提醒了我们 - 前者中的 Buffer 是整个所有的数据行,而后者的 Row 仅仅是包装了每次进入到后者方法中的一行记录,这就是最大的区别。

 

因此,我们可以通过在 ProcessInput() 中循环遍历 Buffer 并每次循环读取一行就可以实现遍历 Buffer 中的所有数据行了。

 public override void Input0_ProcessInput(Input0Buffer Buffer)
{
string fileCreatedDate="";
string line = "";

while (Buffer.NextRow())
{
line
= Buffer.EMPLOYEE;

// 如果行以 FILE CREATED DATE 开始
if(line.StartsWith("FILE CREATED DATE"))
{
// 则只取文件日期部分
fileCreatedDate = line.Substring(19, 10);
}
// 如果达到第二行
else if (line.StartsWith("TOTAL EMPLOYEES"))
{
//MessageBox.Show(line.Substring(16, 10));
//MessageBox.Show(line.Substring(15, 10));
// 创建一个新的输出 Buffer ,并在这个输出中将日期和员工条数取出来放入到 Buffer 中。
FILEMESSAGEBuffer.AddRow();
FILEMESSAGEBuffer.FILECREATEDDATE
= fileCreatedDate;
FILEMESSAGEBuffer.TOTALEMPLOYEES
= int.Parse(line.Substring(16, 10));
}
else if (line.StartsWith("*"))
{
//不做处理
}
else
{
// 剩下的部分是主体内容部分,直接按照固定的列位置描述截取字符串
EMPLOYEEBuffer.AddRow();
EMPLOYEEBuffer.NAME
= line.Substring(0, 50);
EMPLOYEEBuffer.POSITION
= line.Substring(50, 50);
EMPLOYEEBuffer.HIREDDATE
= line.Substring(100, 12);
EMPLOYEEBuffer.BIRTHDATE
= line.Substring(112, 12);
EMPLOYEEBuffer.EMAIL
= line.Substring(124, 50);
EMPLOYEEBuffer.PHONE
= line.Substring(174, 25);
EMPLOYEEBuffer.MARRIAGE
= line.Substring(199, 1) ;
}

}

if (Buffer.EndOfRowset())
{
FILEMESSAGEBuffer.SetEndOfRowset();
EMPLOYEEBuffer.SetEndOfRowset();
}
}

执行包。(可以通过断点调试查看 Script 中方法的调用顺序)

查看结果,这样的一个不规则文件也就处理好了。

把文件数据量加大,其实就会发现当上游文件往下输出时候,已经有一部分数据已经在往下输出了。所以可以看出来,这里的异步是半阻塞控件。

推荐 0
本文由 BIWORK 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册