PB数据管道的实用程序设计技术
王晓学 在PowerBuilder中我们可以通过数据管道,在不同数据库表之间移动数据,实现一个或多个表中的数据拷贝到一个新的或已经存在的目标数据表中。这种操作可以在不同数据库,甚至不同的DBMS之间进行。 PowerBuilder提供了强大的数据管道技术(Data Pipeline)。我们通常使用的有如下两种方式: 直接使用pb画板中提供的实用工具 在应用程序中实现数据移动 本文着重结合具体实例讲述在应用程序中如何实现数据管道技术。在应用程序中使用数据管道有以下五个基本步骤: 创建应用程序所需对象; 执行数据管道初始化操作; 启动数据管道; 处理程序运行中移动数据的错误行; 执行数据移动完毕后的收尾操作。 创建应用程序所需对象 为了在应用程序中实现数据管道,需建立以下几个不同的对象:数据管道对象、支撑用户对象、窗口对象。 创建数据管道对象 这是为实现管道功能所必须的,可在Powerbuilder提供的pipeline画板中创建并定义它的特征。示例在pipeline画板中创建应用程序需要的数据管道对象pipe_user_table01。在此着重说明Commit和Max Errors文本框中参数的意义。 Commit中选中ALL:当所有行在管道操作完成后再向数据库提交,如果操作过程中被终止,则撤消对表的所有操作。 Max Errors文本框中选中NO LIMIT:不论有多少行出错都不终止管道操作。此处视实际编程需要可选其它数字。 创建支撑用户对象 为了提供对属性、事件及函数的支持,需创建一个继承PB管道系统对象的用户对象,通过这个用户对象来管理管道操作。 创建过程如下: 第一步,打开用户对象画板,单击New按钮,在New User Object对话框中选择Class组框中的Standard作为用户对象类型。 第二步,在Select Standard Class Type对话框中选取继承pipeline内置系统对象。 声明管道监控实例 为使用户及时了解程序的运行情况,在创建支撑用户对象画板的工作区使用选单项Declare Instance Variables中声明三个静态文本的监控实例:ist_status_read, ist_status_written, ist_status_error。编辑支撑对象的PipeMeter事件脚本,语句为: ist_status_read.text=String(RowsRead) ist_status_written.text=String(RowsWritten) ist_status_error.text=String(RowsInError) 保存用户对象 示例创建支撑用户对象命名为u_pipe_exchange。 示例创建窗口对象w_yz_pipeline为了完成与管道对象进行交互和监控,该窗口应完成以下基本操作:启动管道→发现错误→显示并修复错误→终止管道操作。在创建此对象时,必须包括一件数据窗口控件,此控件为数据管道提供错误行显示。并且,由应用程序提供此控件的数据窗口对象,不必由用户指定。 执行数据管道初始化操作 执行初始化操作步骤: 连接管道操作的源数据库和目标数据库: 首先在窗口w_yz_pipeline声明事务对象database_source和database_destination。 连接数据库脚本如下: database_source=Create transaction … Connect using database_source; if database_source.SQLCode <> 0 then beep(1) MessagBox(“系统出错:”,“源数据库连接错误”, Exclamation!) Halt End if database_destination=Create transaction … Connect using database_ destination; if database_destination.SQLCode<>0 then beep(1) MessagBox(“系统出错:”,“目标数据库连接错误”, Exclamation!) Halt End if 创建支撑用户对象实例: u_pipe_exchange iuo_pipe_exchange 然后再在uevent_pipe_setup用户事件中创建u_pipe_exchange的实例并赋值给iuo_pipe_exchange变量: iuo_pipe_exchange=CREATE u_pipe_exchange 定义需使用的特定管道对象: 即在相应事件脚本中把某一管道对象的字符串赋给支撑用户对象实例的DataObject属性值。本例中使用了两个不同的管道对象:pipe_user_table01和pipe_user_table02。Cb_start命令按钮的事件操作根据单选按钮的值来决定启动哪个管道对象进行操作,代码为: if rb_create.checked=true then iuo_pipe_exchange.dataobject=’pipe_user_table01’ else iuo_pipe_exchange=’pipe_user_table02’ End if 启动数据管道 在做好初始化工作后,就可以启动管道操作了。为了实现这一功能首先需在相应的事件脚本中写入启动程序代码,利用支撑用户对象的Start函数来启动指定的管道操作。Start函数需指明如下参数: 源数据库的事务对象 目标数据库的事务对象 显示错误信息的数据窗口控件 在管道对象中定义的检索参数 启动管道后,还需验证Start函数的值来判断操作成功与否。 示例脚本: integer pipe_start_result pipe_start_result=iuo_pipeline_exchange.Start(database_source,database_destination,&& dw_errors) choose case pipe_start_result case -1 Beep(1) MessageBox(“程序运行错误”,”管道打开失败”, Exclamation!) Return case -3 Beep(1) MessageBox(“程序运行错误”,”pipe_user_table01表已经存在”, Exclamation!) Return Case -4 Beep(1) MessageBox(“程序运行错误”,”pipe_user_table01表不存在”, Exclamation!) Return End choose 在写入数据信息窗口可以浏览管道操作成功的数据项,在此不再详细说明,用户可以参照数据窗口控件进行编程。 处理程序运行中移动数据的错误行 Start函数把所有的错误行都放置于dw _errors数据窗口控件中,此数据窗口控件为每一行提供了一个错误信息列。 为监控程序进行的情况,在窗口w_yz_pipeline的open事件脚本中加入如下代码: iuo_pipe_exchange.ist_status_read=St_status_read iuo_pipe_exchange.ist_status_written=St_status_written iuo_pipe_exchange.ist_status_error=St_status_error 修复操作调用Repair函数,然后根据函数的返回值判断修复成功与否。相关按钮Clicked事件脚本如下: if u_pipe_exchange.repair (database_destination) <> 1 then beep(1) MessageBox(“修复操作:”,“程序运行错误”,Exclamation!) Return End if 不修复操作按钮Clicked事件脚本如下: dw_errors.Reset() 执行数据移动完毕后的收尾操作 当应用程序完成管道操作后,退出应用程序时,应释放管道操作开始时获得的一些资源。窗口w_yz_pipeline的close事件脚本如下: DESTROY u_pipe_exchange DISCONNECT USING database_source If database_source.SQLCode = -1 then Beep(1) MessageBox(“程序出错:”,”无法关闭源数据库”,Exclamation!) End if DESTROY database_source DISCONNECT USING database_destination; If database_destination.SQLCode = -1 then Beep(1) MessageBox(“程序出错:”,”无法关闭目标数据库”,Exclamation!) End if DESTROY database_destination
下面是我自己实现的一个用timer定时读pipe的例子:
w_pipetimer的open事件
///////////////////////////////////////////////////////
database_destination = create transaction
database_destination.DBMS = "MSS Microsoft SQL Server"
database_destination.Database = "moonprice"
database_destination.ServerName = "wfn"
database_destination.LogPass= '121'
database_destination.LogId = "sa"
database_destination.AutoCommit = False
connect using database_destination;
if database_destination.sqlcode <> 0 then
messagebox("","1error")
end if
database_source = create transaction
// Profile proc_unit
database_source.DBMS = "MSS Microsoft SQL Server"
database_source.Database = "proc_unit"
database_source.ServerName = "wfn"
database_source.LogPass= '121'
database_source.LogId = "sa"
database_source.AutoCommit = False
database_source.DBParm = ""
connect using database_source;
if database_source.sqlcode <> 0 then
messagebox("","2error")
end if
///////////////////////////////////////////////////////
timer(400)
w_pipetimer的timer()事件
integer result
u_pipe i_pipeline
i_pipeline = create u_pipe
i_pipeline.dataobject = "p_yclbyprov"
result = i_pipeline.start(database_source,database_destination,dw_1)
st_read.text = string(i_pipeline.rowsread)
st_error.text = string(i_pipeline.rowsinerror)
st_write.text = string(i_pipeline.rowswritten)
i_pipeline.dataobject = "p_ycl"
result = i_pipeline.start(database_source,database_destination,dw_1)
st_read.text = string(i_pipeline.rowsread)
st_error.text = string(i_pipeline.rowsinerror)
st_write.text = string(i_pipeline.rowswritten)