Database 版 (精华区)
发信人: lizhenguo (夸父·追日), 信区: Database
标 题: 32
发信站: 哈工大紫丁香 (2001年09月26日18:47:27 星期三), 站内信件
bbs.hit.edu.cn
PowerBuilder专栏
[回到开始][上一层][下一篇]
----------------------------------------------------------------------------
----
发信人: carsam (独自偷...), 信区: Database
标 题: PowerBuilder应用开发系列讲座(32)
发信站: 逸仙时空 Yat-sen Channel (Wed Jan 5 12:35:44 2000), 站内信件
PowerBuilder应用开发系列讲座(32)
----------------------------------------------------------------------------
----
为下拉式数据窗口建立缓冲区
在 上 两 期 文 章 中, 我 们 提 到 了 在Master/Detail 风 格 的数 据 窗
口 中 使 用ShareData() 函 数, 可 以 保 持 两 个 数 据 窗 口 中数 据 的 一 致
性。 其 实 这 个 函 数 还 有 着 其 他 很 多 不 同 的 用途。 这 里 我 们 就
另 举 一 例。
许 多 最 终 用 户 在 使 用PowerBuilder 应 用 程 序 时 抱 怨 运行 速 度
太 慢。 一 般 来 讲, 一 个 企 业 级 的 客 户/ 服 务 器 应 用程 序 执 行 速
度 的 瓶 颈 并 不 在 于 代 码 执 行 的 效 率, 而 在 于应 用 向 后 台 数 据
库 查 询 数 据 时 等 待 后 台 响 应 的 时 间。 改进 应 用 软 件 速 度 的 关
键 在 于 减 少 应 用 向 后 台 数 据 库 查 询的 数 据 量, 减 少 网 络 的 数
据 流 量, 其 中 减 少 下 拉 式 数 据 窗口 的 查 询 量 就 是 一 个 有 效 的
方 法。
一 般 的, 为 了 用 户 输 入 方 便 和 避 免 废 键, 在 数 据窗 口 某 些
数 据 列 使 用 下 拉 式 数 据 窗 口 是 程 序 员 经 常 采 用的 方 法。 运 行
一 个 应 用, 某 一 段 时 间 所 处 理 一 般 都 是 相 同或 相 近 的 事 务,
这 样 同 时 打 开 的 不 同 窗 口 和 数 据 窗 口 却很 可 能 同 时 采 用 相 同
的 下 拉 式 数 据 窗 口。 在 显 示 这 些 窗口 前, 当 系 统 执 行 主 数 据
窗 口 的Retrieve() 命 令 时, 总 是 要首 先 到 数 据 库 中 查 询 这 些 下 拉
式 数 据 窗 口 的 数 据。 如 果我 们 能 够 减 少 这 些 查 询, 进 而 减 少
网 络 流 量, 和 后 台 数 据库 服 务 器 进 行 语 法 分 析, 设 计 查 询 算 法
和 执 行 查 询 的 时间, 这 将 能 使 应 用 的 性 能 有 较 大 的 提 高。 这
里 我 们 采 用 的方 法 是 在 客 户 端 建 立 一 个 保 存 结 果 集 的 缓 冲 区
, 并 使 用ShareData 函 数 使 缓 冲 区 的 数 据 同 下 拉 式 数 据 窗 口 的 主
缓 冲 区 建 立共 享。
我 们 将 这 个 数 据 缓 冲 区 建 立 在 一 个 不 可 视 的 窗 口上, 在 这
个 窗 口 为 每 一 个 不 同 的 结 果 集 创 建 一 个 不 同 的用 户 对 象。 首
先 我 们 创 建 一 个 标 准 的 不 可 视 的 用 户 对 象,在 可 选 的 对 象 类
型 中 选 择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_se
rver 窗 口, 这 个 函 数 将 接 受 一 个 数 据 窗 口 和 一 个 列 名 作 为 参数
。
//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() 函 数 如 下, 它接 受 一 个
as_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_size)
IF ids_cache[li_cache_idx].dataobject = as_dataobject THEN
lb_found = TRUE
ELSE
li_cache_idx ++
END IF
LOOP
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
如 果 该 数 据 对 象 不 存 在 于 缓 冲 区 中, 我 们 将 使 用OpenUserOb
ject() 函 数 新 创 建 一 个 用 户 对 象, 并 将 这 个DataStore 的DataObject
属性 赋 值 为as_dataobject, 然 后 调 用SetTransObject() 函 数 和Retrieve()
函 数 查 询 结 果。
在 这 个 隐 含 窗 口 的Open 事 件 中 键 入 下 列 代 码:
i_trans = sqlca
itm_last_refresh = Now ()
// 设 置 起 始 时 间
Timer ( 60 )
在 窗 口 函 数fw_find_dataobject() 中 调 用SetTransObject() 时使 用 的
事 务 变 量 是i_trans, 这 样 做 的 目 的 是 为 了 软 件 更 为通 用。 我 们
在Open 事 件 中 将 这 个 实 例 变 量 赋 值 为SQLCA, 您 也可 以 根 据 需 要
给 予 不 同 的 赋 值。 我 们 使 用 了 一 个 实 例 变量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 事 件 中, 编 写 代 码 根 据 设 定 的时 间 来 调 用f
w_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_interval )
<= ltm_current_time THEN
fw_refresh_all ()
END IF
一 般 在 一 个 大 型 应 用 中, 这 个 对 象 中 往 往 要 有 几十 个 结 果
集。 您 可 能 并 不 希 望 系 统 同 时 更 新 所 有 的 数 据,您 可 以 修 改T
imer 事 件 中 的 代 码, 使 系 统 根 据 一 定 的 算 法,轮 流 更 新 缓 冲 区
中 的 数 据, 而 不 使 用 户 感 觉 到 延 迟。 值 得指 出 的 是, 在 一 般 的
数 据 窗 口 中 的dddw, 除 了 在 创 建 时 系统 会 自 动 对 该 数 据 窗 口 中
的 所 有dddw 进 行Retrieve() 以 外, 在运 行 过 程 中 如 果 没 有 程 序 明
确 指 明 某 个dddw 执 行Retrieve() 函 数, 系 统 是 不 会 自 动 更 新 其 数
据 的。 因 此 采 用 本 文 推 荐的 方 法 还 可 以 保 持 下 拉 式 数 据 窗 口
中 的 数 据 接 近 后 台 服务 器 中 的 最 新 数 据。 如 果 您 在 应 用 中 必
须 使 下 拉 式 数 据窗 口 中 的 数 据 为 后 台 的 最 新 数 据, 也 可 以 调
用wf_refresh_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 所 使 用 的 缓 冲 区, 然 后 更 新 该 缓 冲区 的 数 据 即 可
。
--
我想自由自在地飞......
飞过大海...
飞过沙漠...
飞翔在星的夜空......
※ 来源:.逸仙时空 Yat-sen Channel bbs.zsu.edu.cn.[FROM: 202.116.90.29]
----------------------------------------------------------------------------
----
[回到开始][上一层][下一篇]
欢迎访问Cterm主页
--
《列子·汤问》:“夸父不量力,欲追日影,逐之于隅谷之际。渴欲 得饮,赴饮河渭
。河渭不足,将走北饮大泽。未至,道渴而死。”
※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 202.118.229.154]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:2.568毫秒