Database 版 (精华区)
发信人: wodeji (西西), 信区: Database
标 题: [转载] owerBuilder 开 发 系 列 谈 (32)
发信站: 紫 丁 香 (Tue Sep 29 17:53:29 1998), 站内信件
【 以下文字转载自 Programming 讨论区 】
【 原文由 two 所发表 】
Email: sjhzyz@public.bta.net.cn
在 上 两 期 文 章 中, 我 们 提 到 了 在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_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() 函 数 如 下, 它 接 受 一 个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
// 如 果 该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, 然 后 调 用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
事 件 中, 编 写 代 码 根 据 设 定 的 时 间 来 调 用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_interval )
<= ltm_current_time THEN
fw_refresh_all ()
END IF
一 般 在 一 个 大 型 应 用 中, 这 个 对 象 中 往 往 要 有 几 十 个 结 果 集。 您 可
能 并 不 希 望 系 统 同 时 更 新 所 有 的 数 据, 您 可 以 修 改Timer 事 件 中 的 代
码, 使 系 统 根 据 一 定 的 算 法, 轮 流 更 新 缓 冲 区 中 的 数 据, 而 不 使 用 户
感 觉 到 延 迟。 值 得 指 出 的 是, 在 一 般 的 数 据 窗 口 中 的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 所 使 用 的 缓 冲 区, 然 后 更 新 该 缓 冲 区 的 数 据 即 可。
--
※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: 202.97.236.132]
--
※ 转载:.紫 丁 香 bbs.hit.edu.cn.[FROM: whs.hit.edu.cn]
--
※ 转载:.紫 丁 香 bbs.hit.edu.cn.[FROM: cadcam.hit.edu.c]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:203.536毫秒