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毫秒