荔园在线
荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀
[回到开始]
[上一篇][下一篇]
发信人: Peter (小飞侠), 信区: Program
标 题: PowerBuilder应用开发系列讲座
发信站: BBS 荔园晨风站 (Thu Jan 21 22:39:51 1999), 转信
为下拉式数据窗口建立缓冲区
许多最终用户在使用PowerBuilder应用程序时抱怨运行速度太慢。
一般来讲,一个企业级的客户/服务器应用程序执行速度的瓶颈并不在
于代码执行的效率,而在于应用向后台数据库查询数据时等待后台响
应的时间。改进应用软件速度的关键在于减少应用向后台数据库查询
的数据量,减少网络的数据流量,其中减少下拉式数据窗口的查询量就
是一个有效的方法。
一般情况下,为了用户输入方便和避免废键,在数据窗口的某些数
据列使用下拉式数据窗口是程序员经常采用的方法。运行一个应用,
某一段时间所处理的一般都是相同或相近的事务,这样同时打开的不
同窗口和数据窗口却很可能同时采用相同的下拉式数据窗口。在显示
这些窗口前,当系统执行主数据窗口的Retrieve()命令时,总是要首先
到数据库中查询这些下拉式数据窗口的数据。如果我们能够减少这些
查询,进而减少网络流量以及后台数据库服务器进行语法分析、设计
查询算法和执行查询的时间,将能使应用的性能得到较大提高。这里
我们采用的方法是在客户端建立一个保存结果集的缓冲区,并利用Sha
reData函数使缓冲区的数据同下拉式数据窗口的主缓冲区建立共享。
我们将这个数据缓冲区建立在一个不可视的窗口上,在这个窗口
中为每一个不同的结果集创建一个不同的用户对象。首先我们创建一
个标准的不可视的用户对象,在可选的对象类型中选择DataStore,我
们并不需要为这个用户对象编写任何代码,只要将其保存为u_dsa即可
。
我们创建一个窗口w_resultset_server作为结果集服务器,在这
个不可视的窗口中声明这样一些实例变量:
//缓冲区大小
PROTECTED integer ii_cache_size
//缓冲区
PROTECTED u_dsa ids_cache[]
//我们用以检索结果集的事务对象
PROTECTED transaction i_trans
//更新结果集的时间(设为30秒)
PROTECTED long il_refresh_interval = 1800
//更新的起始时刻
PROTECTED time itm__last_refresh
使用dddw的窗口将通过fw_share_dddw()函数来访问w_resultset
_server窗口,这个函数将接受一个数据窗口和一个列名作为参数。
//public function integer fw_share_dddw
//参数: DataWindow adw_parent
//string as_column_name 表现形式为dddw列名
integer li_cache_idx
DataWindowchild dwc
string ls_dataobject_name
//dddw所使用dataobject的名称
ls_dataobject_name = adw_parent.Describe( as_column_name
+ ".dddw.name" )
IF ls_dataobject_name = "" THEN RETURN 0
// 该dataobject是否存在缓冲区中
li_cache_idx = fw_find_dataobject (ls_dataobject_name)
IF li_cache_idx < 1 THEN RETURN 0
// 同子数据窗口共享数据
adw_parent.GetChild ( as_column_name, dwc )
RETURN ids_cache[li_cache_idx].ShareData (dwc)
在这个函数中,为确定下拉式数据窗口所使用的数据窗口的名称,
首先使用了Describe( )函数来获得该列的dddw.name属性。如果该列
名没有找到,或该列的表现形式不是下拉式数据窗口,这个函数的返回
值为"";接下来调用fw_find_dataobject()函数,以确定这个数据结果
集是否在缓冲区中,如不存在,就新创建一个;最后使用ShareDate()函
数将缓冲区中结果集同下拉式数据窗口共享数据。
这个函数中调用的fw_find_dataobject()函数如下:它接受一个a
s_dataobject参数,并使用DO...WHILE循环在缓冲区中查找该对象的
结果集,如找到将lb_found设为True,否则设为False。
//protected function integer fw_find_dataobject
//参数: string as_dataobject
integer li_cache_idx = 1
boolean lb_found = FALSE
u_dsa lds_new_entry
//定位dataobject所在的缓冲区
DO WHILE (NOT lb_found) and (li_cache_idx <= ii_cache_si
ze)
IF ids_cache[li_cache_idx].dataobject = as_dataobject
THEN
lb_found = TRUE
ELSE
li_cache_idx ++
END IF
LOOP
// 如果该dataobject不存在于缓冲区中,则创建一个新入口
IF NOT lb_found THEN
IF OpenUserObject (lds_new_entry) < 1 THEN
RETURN 0
END IF
lds_new_entry.dataobject = as_dataobject
IF lds_new_entry.SetTransObject (i_trans) < 1 THEN
RETURN 0
END IF
IF lds_new_entry.Retrieve () < 0 THEN
RETURN 0
END IF
ii_cache_size ++
ids_cache[ii_cache_size] = lds_new_entry
li_cache_idx = ii_cache_size
END IF
RETURN li_cache_idx
如果该数据对象不存在于缓冲区中,我们将使用OpenUserObject(
)函数新创建一个用户对象,并将这个DataStore的DataObject属性赋
值为as_dataobject,然后调用SetTransObect ()函数和Retrieve()函
数查询结果。
在这个隐含窗口的Open事件中键入下列代码:
i_trans = sqlca
itm_last_refresh = Now ()
//设置起始时间
Timer ( 60 )
在窗口函数fw_find_dataobject()中调用SetTransObject()时使
用的事务变量是i_tra ns,这样做的目的是为了使软件更为通用。我
们在Open事件中将这个实例变量赋值为SQLA,您也可以根据需要给予
不同的赋值。我们使用了一个实例变量itm_last_refresh作为计时器
, 并且设定每一分钟中断一次,以使窗口根据不同的需要更新缓冲区
中的数据。
下面的一个窗口函数fw_refresh_all用以更新缓冲区数据:
//public subroutine fw_refresh_all ()
integer li_cache_idx
// 更新所有缓冲区
FOR li_cache_idx = 1 TO ii_cache_size
ids_cache[li_cache_idx].Retrieve ()
NEXT
//重新设置更新缓冲区的时间
i_tm_last_refresh = Now ()
我们在w_resultset_server的Open事件中对一个计时器进行了初
始化,同时还初始化了一个计时变量itm_last_refresh,下面的工作就
是在Timer事件中编写根据设定的时间来调用fw_refresh_all()的代
码。
time ltm_current_time
integer li_cache_idx
//当前时间
current_time = Now ()
//考虑过午夜的特殊情况
IF ltm_current_time < itm_last_refresh THEN
fw_refresh_all ()
//检测已过的时间间隔
ELSEIF RelativeTime ( itm_last_refresh, ii_refresh_inter
val ) <= ltm_curren t_time THEN
fw_refresh_all ()
END IF
一般在一个大型应用中,这个对象中往往要有几十个结果集。开
发者可能并不希望系统同时更新所有的数据,故可以修改Timer事件中
的代码,使系统根据一定的算法,轮流更新缓冲区中的数据,而不使用
户感觉到延迟。值得指出的是,在一般的数据窗口中的dddw,除了在创
建时系统会自动对该数据窗口中的所有dddw进行Retrieve()以外,在
运行过程中如果没有程序明确指明某个dddw执行Retrieve()函数,系
统是不会自动更新其数据的。因此采用本文推荐的方法还可以保持下
拉式数据窗口中的数据接近后台服务器中的最新数据。如果在应用中
必须使下拉式数据窗口中的数据为后台的最新数据,也可以调用wf_re
fresh_resultset(强制缓冲区更新数据,使用的参数有两个:数据窗口
名称和列名,代码如下:
//public function boolean fw_refresh_resultset()
//参数: DataWindow adw_parent
//string as_column_name 数据窗口中为dddw的列名
integer li_cache_idx
string ls_dataobject_name
//dddw所使用dataobject的名称
ls_dataobject_name = adw_parent.Describe( as_column_name
+ ".dddw.name" )
IF ls_dataobject_name = ""THEN RETURN False
//该dataobject是否存在缓冲区中
li_cache_idx = fw_find_dataobject (ls_dataobject_name)
IF li_cache_idx < 1 THEN RETURN False
//更新缓冲区内的数据
ids_cache[li_cache_idx].Retrieve()
RETURN True
在这段代码中,我们首先使用fw_find_dataobject函数找到要更
新数据的dddw所使用的缓冲区,然后更新该缓冲区的数据即可。
--
※ 来源:.BBS 荔园晨风站 bbs.szu.edu.cn.[FROM: 192.168.1.3]
[回到开始]
[上一篇][下一篇]
荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店