PowerBuilder应用开发系列讲座(32)
为下拉式数据窗口建立缓冲区
在上两期文章中,我们提到了在Master/Detail风格的数据窗口中使用ShareData()函数,可以保持两个数据窗口中数据的一致性。其实这个函数还有着其他很多不同的用途。这里我们就另举一例。
许多最终用户在使用PowerBuilder应用程序时抱怨运行速度太慢。一般来讲,一个企业级的客户/服务器应用程序执行速 度的瓶颈并不在于代码执行的效率,而在于应用向后台数据库查询数据时等待后台响应的时间。改进应用软件速度的关键在于减少应用向后台数据库查询的数据量,减少网络的数据流量,其中减少下拉式数据窗口的查询量就是一个有效的方法。
一般的,为了用户输入方便和避免废键,在数据窗口某些数据列使用下拉式数据窗口是程序员经常采用的方法。运行一个应用,某一段时间所处理一般都是相同或相近的事务,这样同时打开的不同窗口和数据窗口却很可能同时采用相同的下拉式数据窗口。在显示这些窗口前,当系统执行主数据窗口的Retrieve()命令时,总是要首先到数据库中查询这些下拉式数据窗口的数据。如果我们能够减少这些查询,进而减少网络流量,和后台数据库服务器进行语法分析,设计查询算法和执行查询的时间,这将能使应用的性能有较大的提高。这里我们采用的方法是在客户端建立一个保存结果集的缓冲区,并使用ShareData函数使缓冲区的数据同下拉式数据窗口的主缓冲区建立共享。
我们将这个数据缓冲区建立在一个不可视的窗口上,在这个窗口为每一个不同的结果集创建一个不同的用户对象。首先我们创建一个标准的不可视的用户对象,在可选的对象类型中选择DataStore,我们并不需要为这个用户对象编写任何代码,只要将其保存为u_dsa即可。
我们创建一个窗口w_resultset_server作为结果集服务器,在这个不可视的窗口中声明这样一些实例变量: //缓冲区大小
PROTECTEDintegerii_cache_size
//缓冲区
PROTECTEDu_dsaids_cache[]
//我们用以检索结果集的事务对象
PROTECTEDtransactioni_trans
//更新结果集的时间(设为30秒)
PROTECTEDlongil_refresh_interval=1800
//更新的起始时刻
PROTECTEDtimeitm__last_refresh
使用dddw的窗口将通过fw_share_dddw()函数来访问w_resultset_server窗口,这个函数将接受一个数据窗口和一个列名作为参数 。
//publicfunctionintegerfw_share_dddw
//参数:DataWindowadw_parent
//stringas_column_name表现形式为dddw列名
integerli_cache_idx
DataWindowchilddwc
stringls_dataobject_name
//dddw所使用dataobject的名称
ls_dataobject_name=adw_parent.Describe(as_column_name+“.dddw.name” )
IFls_dataobject_name=“”THENRETURN0
//该dataobject是否存在缓冲区中
li_cache_idx=fw_find_dataobject(ls_dataobject_name)
IFli_cache_idx$#@60;1THENRETURN0
//同子数据窗口共享数据
adw_parent.GetChild(as_column_name,dwc)
RETURNids_cache[li_cache_idx].ShareData(dwc)
这个函数中调用的fw_find_dataobject()函数如下,它接受一个as_dataobject参数,并使用DO...WHILE循环在缓冲区中查找该对象的结果集,如找到将lb_found设为True,否则设为False。
//protectedfunctionintegerfw_find_dataobject
//参数:stringas_dataobject
integerli_cache_idx=1
booleanlb_found=FALSE
u_dsalds_new_entry
//定位dataobject所在的缓冲区
DOWHILE(NOTlb_found)and(li_cache_idx$#@60;=ii_cache_size)
IFids_cache[li_cache_idx].dataobject=as_dataobjectTHEN
lb_found=TRUE
ELSE
li_cache_idx++
ENDIF
LOOP
//如果该dataobject不存在与缓冲区中,则创建一个新入口
IFNOTlb_foundTHEN
IFOpenUserObject(lds_new_entry)$#@60;1THEN
RETURN0
ENDIF
lds_new_entry.dataobject=as_dataobject
IFlds_new_entry.SetTransObject(i_trans)$#@60;1THEN
RETURN0
ENDIF
IFlds_new_entry.Retrieve()$#@60;0THEN
RETURN0
ENDIF
ii_cache_size++
ids_cache[ii_cache_size]=lds_new_entry
li_cache_idx=ii_cache_size
ENDIF
RETURNli_cache_idx
在这个隐含窗口的Open事件中键入下列代码:
i_trans=sqlca
itm_last_refresh=Now()
//设置起始时间
Timer(60)
下面的一个窗口函数fw_refresh_all用以更新缓冲区数据:
//publicsubroutinefw_refresh_all()
integerli_cache_idx
//更新所以缓冲区
FORli_cache_idx=1TOii_cache_size
ids_cache[li_cache_idx].Retrieve()
NEXT
//重新设置更新缓冲区的时间
i_tm_last_refresh=Now()
timeltm_current_time
integerli_cache_idx
//当前时间
current_time=Now()
//考虑过午夜的特殊情况
IFltm_current_time$#@60;itm_last_refreshTHEN
fw_refresh_all()
//检测已过的时间间隔
ELSEIFRelativeTime(itm_last_refresh,ii_refresh_interval)
$#@60;=ltm_current_timeTHEN
fw_refresh_all()
ENDIF
//publicfunctionbooleanfw_refresh_resultset()
//参数:DataWindowadw_parent
//stringas_column_name数据窗口中为dddw的列名
integerli_cache_idx
stringls_dataobject_name
//dddw所使用dataobject的名称
ls_dataobject_name=adw_parent.Describe(as_column_name+“.dddw.name” )
IFls_dataobject_name=“”THENRETURNFalse
//该dataobject是否存在缓冲区中
li_cache_idx=fw_find_dataobject(ls_dataobject_name)
IFli_cache_idx$#@60;1THENRETURNFalse
//更新缓冲区内的数据
ids_cache[li_cache_idx].Retrieve()
RETURNTrue
- 最新文章
- PowerBuilder应用开发系列讲座(20)[01-04]
- PowerBuilder应用开发系列讲座(14)[01-04]
- 关于PB播放AVI文件的补充[01-04]
- 在PB中应用灵活多样的排序[01-04]
- 如何实现PB应用程序的屏幕保护功能[01-04]
- PowerBuilder数据录入同步显示[01-04]
- 相关文章
- PowerBuilder应用开发系列讲座(20)[01-04]
- PowerBuilder应用开发系列讲座(14)[01-04]
- 在PB中应用灵活多样的排序[01-04]
- 如何实现PB应用程序的屏幕保护功能[01-04]
- PowerBuilder应用开发系列讲座(16)[01-04]
- 用PowerBuilder6.0建立B/S结构的应用程序[01-04]
