为SSIS编写简单的同步转换组件

上一篇讲到了同步转换和异步转换的概念。通常情况下,大部分转换都是同步的,即收到一行就处理一行。(注意,这样说可能不是很准确,实际上即便是同步机制,数据流也会适当的进行缓存的,只不过这种缓存对用户数透明的,用户可以理解为收到一行就处理一行)

同步转换组件可以很简单,也可以很复杂。这取决于你的设计逻辑。

这一篇我还是用一个简单的例子来讲解,旨在让大家了解同步转换组件的设计流程。

需求:我们这个组件很简单,就是将输入列中的文本列的所有字母全部转换为大写。

1. 准备一个类型

    [DtsPipelineComponent(

          ComponentType=ComponentType.Transform,

          Description="这是我的一个自定义数据转换"

,

          DisplayName="大写转换"

)]

    public

 class

 MyTransfomation:PipelineComponent

    {

    }

这个类型是我们上次准备好的,但没有做实现。【注意】我把DisplayName改成了“大写转换”

如果你是从头开始做,那么请注意,添加以下的引用和using语句

2. 实现代码

代码将由几个部分组成

首先仍然是 ProvideComponentProperties方法,这个方法准备一些元数据。一般都是定义输入和输出的属性。该方法的占位代码如下

        public

 override

 void

 ProvideComponentProperties()

        {

            base

.ProvideComponentProperties();

        }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

我们对其加以修改。我们需要知道的一个基础知识就是:任何一个转换,即便不做任何事情,它也自动具有一个默认的输入和输出。

我们在这个代码里面给默认的输入和输出做一个重命名。这样做的目的是让它们更加形象

        /// <summary>

        /// 这个方法提供组件必须的一些属性。

        /// 这里主要给默认的输入和输出重命名,让它更加形象

        /// </summary>

        public

 override

 void

 ProvideComponentProperties()

        {

            base

.ProvideComponentProperties();

            ComponentMetaData.InputCollection[0].Name = "大写转换输入"

;

            ComponentMetaData.OutputCollection[0].Name = "大写转换输出"

;

            //ComponentMetaData.OutputCollection[1].SynchronousInputID = ComponentMetaData.InputCollection[0].ID;

            //如果调用了base.ProvideComponentProperties,则可以省略这句代码

        }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

第二步:我们重写PreExecute方法,这个方法为执行做准备。我们这里的需求比较简单,就是检查所有最终确定的输入列,如果他们的类型是字符型(不管是STR还是WSTR),我们就对它们做一个记号

        List<int

> _columns = new

 List<int

>();//这个集合来保存需要处理的列的索引号

        /// <summary>

        /// 这个方法是ProcessInput之前的准备工作。

        /// 我们检测所有输入列中类型为字符型的,并将它的索引号记录起来

        /// 为了让ProcessInput能使用到这个信息,我们定义一个公用变量

        /// </summary>

        public

 override

 void

 PreExecute()

        {

            IDTSInput90 input = ComponentMetaData.InputCollection[0];

            IDTSInputColumnCollection90 columns = input.InputColumnCollection;

            foreach

 (IDTSInputColumn90 item in

 columns)

            {

                if

 (item.DataType == DataType.DT_WSTR || item.DataType == DataType.DT_STR)

                {

                    _columns.Add(BufferManager.FindColumnByLineageID(input.Buffer, item.LineageID));

                }

            }

        }
 
第三步:我们重写ProcessInput方法。这个方法会被数据流任务多次调用。我们就是不断地进行处理,直到数据源不再能提供数据为止。
        public

 override

 void

 ProcessInput(int

 inputID, PipelineBuffer buffer)

        {

            while

 (buffer.NextRow())//从这句话可以理解,其实虽然说是同步,但也可能是缓冲了几行后才处理,而不一定是一行处理一次

            {

                foreach

 (int

 index in

 _columns)

                {

                    string

 str = buffer.GetString(index);

                    buffer.SetString(index, str.ToUpper());

                }

            }

        }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

我们这里只是对输入的buffer进行处理。注意,这里很有意思的是,我们其实很简单的,先把buffer中某个列的值读出来,然后将其转回大写之后写回去即可。

3. 重新编译项目,部署。在BI Studio中进行测试

我们只需要勾选上有关的输入列即可。其他不需要任何的设置

现在就可以执行任务了。如果不出意外,任务能够成功执行,如下图所示

我们最后打开生成的那个文本文件进行验证

我们看到,第一列和第三列的文本全部被处理成了大写。

我们也可以在数据流中添加“查看器”,很清楚的看到从“文件夹数据源”到“大写转换”这个管道中,字符是小写的

而在“大写转换”到“平面文件目标”这个管道中,字符就被转变为大写了

补充:

该转换组件已经可以工作了。但我们还是可以添加下面的一些功能(例如验证),以便让它更加完整

        public

 override

 DTSValidationStatus Validate()

        {

            //验证组件,至少要有一个输入列

            IDTSInput90 input = ComponentMetaData.InputCollection[0];

            if

 (input.InputColumnCollection.Count > 0)

                return

 DTSValidationStatus.VS_ISVALID;

            ComponentMetaData.FireWarning(0, 

                ComponentMetaData.Name, 

                "至少应该选择一个输入列"

, 

                string

.Empty, 

                0);

            return

 DTSValidationStatus.VS_ISBROKEN;

        }

        public

 override

 void

 DeleteInput(int

 inputID)

        {

            throw

 new

 Exception("不能删除输入"

);

        }

        public

 override

 IDTSCustomProperty90 SetInputProperty(int

 inputID, 

            string

 propertyName, object

 propertyValue)

        {

            throw

 new

 Exception("不能修改输入"

);

        }

这样的话,如果用户没有选择列,则会出现下面的错误

0
时间: 2024-10-07 14:42:52

为SSIS编写简单的同步转换组件的相关文章

编写轻量ajax组件01-对比webform平台上的各种实现方式

前言 Asp.net WebForm 和 Asp.net MVC(简称MVC) 都是基于Asp.net的web开发框架,两者有很大的区别,其中一个就是MVC更加注重http本质,而WebForm试图屏蔽http,为此提供了大量的服务器控件和ViewState机制,让开发人员可以像开发Windows Form应用程序一样,基于事件模型去编程.两者各有优缺点和适用情景,但MVC现在是许多Asp.net开发者的首选. WebForm是建立在Asp.net的基础上的,Asp.net提供了足够的扩展性,我

VC++编写简单串口上位机程序

转载: http://blog.sina.com.cn/s/articlelist_1809084904_0_1.html VC++编写简单串口上位机程序 串口通信,MCU跟PC通信经常用到的一种通信方式,做界面.写上位机程序的编程语言.编译环境等不少,VB.C#.LABVIEW等等,我会的语言很 少,C语言用得比较多,但是还没有找到如何用C语言来写串口通信上位机程序的资料,在图书管理找到了用VC++编写串口上位机的资料,参考书籍,用自己相 当蹩脚的C++写出了一个简单的串口上位机程序,分享一下

关于Socket编写简单聊天工具的总结(原创)

这段时间再看socket编程,虽然现在是刚刚接触,但是还是忍不住想写一篇总结,来激励自己努力学习,写的不好的地方,还请大家指教啊! 下面针对一个简单的发送消息和文件的程序说说吧.   首先是服务器需要准备二个Socket和二个Thread如下: //和客户机进行通信 private Socket sckCommit; //监听客户机 private Socket sckListen; private Thread thdListen; private Thread thdCommit; 对客户机

封装一个简单的solrserver组件

一个简单的solrserver组件 实现索引更新的异步处理,以及查询接口,日志/线程池/队列监控没有加上. SolrDocment封装 接口: public interface ISolrDocument { public SolrInputDocument convertToInputDocument() throws Exception; public void buildSolrDocument(SolrDocument document) throws Exception; } 实现:

[简明python教程]学习笔记之编写简单备份脚本

[[email protected] 0503]# cat backup_ver3.py #!/usr/bin/python #filename:backup_ver3.py import os import time #source source=['/root/a.sh','/root/b.sh','/root/c.sh'] #source='/root/c.sh' #backup dir target_dir='/tmp/' today=target_dir+time.strftime('

python编写简单的html登陆页面(3)

1  在python编写简单的html登陆页面(2)的基础上在延伸一下: 可以将静态分配数据,建立表格,存放学生信息 2  加载到静态数据 3  html的编写直接在表格里添加一组数据就行了 4  VS Code上面跟前面的后台类似,添加一个content再链接到html就可以了 @app.route('/content')def content(): return render_template('content.html') return 'content.....'

python编写简单的html登陆页面(2)

1  在python编写简单的html登陆页面(1)的基础上在延伸一下: 可以将动态分配数据,实现页面跳转功能: 2  跳转到新的页面:return render_template('home1.html') 3  后台代码如下 4  前端html:

scapy编写简单的ARP扫描脚本 本课程基于 Python 的 scapy 模块编写,适合有 Python 基础的同学学习,最终完成一个简单的 ARP 扫描脚本。

scapy编写简单的ARP扫描脚本 本课程基于 Python 的 scapy 模块编写,适合有 Python 基础的同学学习,最终完成一个简单的 ARP 扫描脚本.

《COM原理与应用》学习笔记——一个简单的COM组件的实现

今天带来一个简单的COM组件的实现,非常的简单.这个组件只是简单的完成了整数的加减乘除~ 首先,先罗列需要的COM接口,这里需要的接口非常简单,就是加减乘除的接口.所以定义一个ICalc类,当然这个类继承于IUnknown. 1 class ICalc : public IUnknown 2 { 3 public: 4 virtual long __stdcall add(long a, long b) = 0; 5 virtual long __stdcall minus(long a, lo