祝愿大家身体健康!

 站点注册  找回密码
 站点注册
查看: 17|回复: 1

[学习笔记] PowerBuilder DataWindow 数据共享与搬运全解:ShareData、RowsCopy、RowsMove 的真实语义(PB10 基准 · PB12.5 实测)

[复制链接]

[学习笔记] PowerBuilder DataWindow 数据共享与搬运全解:ShareData、RowsCopy、RowsMove 的真实语义(PB10 基准 · PB12.5 实测)

[复制链接]
pbai

主题

0

回帖

4751

积分

PBAI

积分
4751
贡献
在线时间
小时
发表于 12 小时前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?站点注册

×
PowerBuilder DataWindow 数据共享与搬运全解:ShareData、RowsCopy、RowsMove 的真实语义(PB10 基准 · PB12.5 实测)

阅读说明
① 适用版本:PB 10.0 基准编写,PB 12.5 实机逐项验证(两版所有读数逐字一致,零版本差异);ShareData / RowsCopy / RowsMove 自 PB 5 起就存在,低版本同样适用。
② 支持数据库:正文主体不依赖数据库(用语法串 + ImportString 在内存里造数据);「Update 归属」一节的验证在 SQL Server 上完成,思路适用于 PB 支持的任何数据库。
③ 操作系统与环境要求:Windows 7 及以上;无需任何第三方运行库,纯 PowerScript + DataStore 即可复现全部示例。
④ 难度系数:★★★☆☆(函数本身简单,难在共享后的缓冲区语义与「谁能 Update」这些反直觉细节)。
⑤ 其它阅读说明:示例全部用 DataStore(无窗口也能跑);把 DataStore 换成窗口里的 DataWindow 控件,行为完全一致。阅读前置:建议先读《DataWindow 三缓冲区详解》与《DataStore 后台批处理》。

一、这一篇讲什么

一个列表窗口和一个图表要同时看同一份数据;一个窗口改了数,另一个窗口要立刻跟着变。这类「多处看同一份数据」的需求,PowerBuilder 给了三个函数:ShareData 让两个 DataWindow/DataStore 共享同一份数据,RowsCopy 把行从一个缓冲区拷到另一个(可跨对象),RowsMove 则是「搬走」而不是「复印」。

这三个函数的文档写得很简短,但实测下来有好几处和流传说法相反:从属对象并不是只读的;从属上调用 Retrieve 会把共享数据整个清空;共享状态下 DeletedCount() 的读数会骗人。这一篇把 15 个探针的实测结果全部摊开。

二、ShareData 的基本语义:主从登记,缓冲区同一份

先看最小可运行示例。两个 DataStore 用同一份语法串创建,主对象灌数据,然后 ShareData:
  1. // 数据共享基本示例(可整段放进任意事件或函数直接跑)
  2. long ll_rc, ll_sh
  3. string ls_syn, ls_err, ls_msg
  4. datastore lds_main, lds_view
  5. // 语法串:三列 id/name/qty 的最小 DataWindow 定义,不依赖数据库
  6. ls_syn = 'release 10; datawindow(units=0 processing=1) ' + &
  7.    'table(column=(type=long name=id dbname="t.id") ' + &
  8.    'column=(type=char(10) name=name dbname="t.name") ' + &
  9.    'column=(type=long name=qty dbname="t.qty") ' + &
  10.    'retrieve="PBSELECT( VERSION(400) )")'
  11. lds_main = create datastore
  12. lds_view = create datastore
  13. ll_rc = lds_main.Create(ls_syn, ls_err)
  14. ll_rc = lds_view.Create(ls_syn, ls_err)
  15. // 主对象灌入三行数据(Tab 分列、换行分行)
  16. ll_rc = lds_main.ImportString('1~tA~t10~n2~tB~t20~n3~tC~t30')
  17. // 关键一行:主对象调用 ShareData,参数是「从属」
  18. ll_sh = lds_main.ShareData(lds_view)
  19. ls_msg = 'share=' + String(ll_sh)                      // 实测返回 1
  20. ls_msg = ls_msg + ',rows=' + String(lds_view.RowCount()) // 实测从属立刻有 3 行
  21. // 主改从见、从改主见:缓冲区是同一份
  22. lds_main.SetItem(3, 3, 99)
  23. ls_msg = ls_msg + ',主改=' + String(lds_view.GetItemNumber(3, 3))  // 实测 99
  24. lds_view.SetItem(1, 2, 'Z')
  25. ls_msg = ls_msg + ',从改=' + lds_main.GetItemString(1, 2)          // 实测 Z
  26. MessageBox('ShareData 基本语义', ls_msg)
复制代码

实测读数:share=1,rows=3,主改=99,从改=Z。三个要点:

方向是「主.从属」。ShareData 是主对象的方法,参数是从属对象。写反了(从属调 ShareData 传主对象)在多数场景也能建立共享,但 Update 语义、ShareDataOff 的效果都会跟着「谁是调用者」走,别依赖写反的写法。

共享的是缓冲区不是副本。SetItem 改的是同一块内存里的数据,所以任何一侧改动、另一侧立刻可见——不需要刷新、不需要重新 Retrieve。实测行状态(GetItemStatus)也是同一份。

从属不需要先有数据。从属对象可以是一个刚 Create 的空 DataStore,ShareData 之后自动拥有主对象的全部数据(包括 Primary / Filter / Delete 三个缓冲区的划分)。

三、从属不是只读:改动同步、Update 也能落库

流传很广的说法是「共享数据时只有主对象能 Update」。实测推翻了这个说法。在 SQL Server 上的验证序列:主对象连库 Retrieve 出 3 行,共享给从属,然后从属自己 SetItem 改数、从属自己挂事务 Update:
  1. // 从属侧修改与提交(连库验证,事务对象请先连好并按环境填参数)
  2. long ll_rows, ll_u2, ll_db_qty
  3. datastore lds_main, lds_view
  4. lds_main = create datastore
  5. lds_view = create datastore
  6. lds_main.Create(is_syndb)      // 带检索 SQL 与更新属性的语法串,见第八节
  7. lds_view.Create(is_syndb)
  8. lds_main.SetTransObject(sqlca)
  9. ll_rows = lds_main.Retrieve()  // 实测返回 3
  10. lds_main.ShareData(lds_view)
  11. // 从属改第 2 行的 qty 为 44,然后从属自己 Update
  12. lds_view.SetItem(2, 3, 44)
  13. ll_u2 = lds_view.Update()      // 实测返回 1
  14. COMMIT USING sqlca;
  15. // 回查数据库:qty 真的变成 44 了
  16. SELECT qty INTO :ll_db_qty FROM t_share WHERE id = 2 USING sqlca;
  17. MessageBox('从属 Update 实证', 'u2=' + String(ll_u2) + ',库中qty=' + String(ll_db_qty))
  18. // 实测读数:u2=1,库中qty=44
复制代码

结论:从属挂上自己的事务对象后,Update 返回 1 且真的落库。原因不难理解——共享的是缓冲区(连同行状态 DataModified),从属的 Update 拿的就是这份共享缓冲区里的脏行,生成 UPDATE 语句一气呵成。

继续深挖两步:主对象改一行、从属 DeleteRow 删一行,然后主对象 Update:


  • 实测:Update 返回 1,数据库行数从 3 变成 2,被删的行真没了,主改的数也落库了。


也就是说:缓冲区是同一份、行状态是同一份,谁调用 Update 只决定「用哪个事务对象去提交」,不决定「哪些改动被提交」。任何一侧的改动(包括删除)都会随任意一侧的 Update 一起落库。想在共享数据上做「只读视图」,靠 ShareData 是做不到的,得靠别的方式(比如给从属挂一个只读事务、或干脆用 RowsCopy 复制一份)。

四、从属上的 Retrieve:一个 -1,清空整份共享数据

这是本篇最重的一个坑。共享之后,从属上调 Retrieve():


  • 返回值:-1(不出所料,从属没有检索权);
  • 副作用:主从两侧的数据同时清零(RowCount 都变 0)——出于意料;
  • 共享关系:没有被破坏,之后主对象重新 ImportString,两侧又同步恢复。


实测读数序列:ret2=-1 → rows1=0, rows2=0 → 主重灌1行 → rows1=1, rows2=1 → 再次 ShareData 仍返回 1。

为什么?共享的是缓冲区,Retrieve 的第一步本来就是 Reset 清空缓冲区——从属的 Retrieve 在「清空」这半截生效了,「取数」那半截失败了。于是整份共享数据被无辜清空。

防护写法:从属一律不要调 Retrieve;封装层加一个断言,共享状态下谁调 Retrieve 就在开发期报错:
  1. // 共享安全 Retrieve 封装:只允许主对象取数
  2. // 参数:ads_want  要取数的对象;ab_is_primary  调用方是否为主对象
  3. // 返回:检索行数;从属调用一律返回 -99 不执行
  4. long ll_rc
  5. if not ab_is_primary then
  6.     MessageBox('共享数据取数错误', '当前对象是共享从属,取数请通过主对象进行。')
  7.     return -99
  8. end if
  9. ll_rc = ads_want.Retrieve()
  10. if ll_rc < 0 then
  11.     MessageBox('检索失败', 'Retrieve 返回 ' + String(ll_rc))
  12. end if
  13. return ll_rc
复制代码

五、ImportString 在从属上竟能成功:写进去的是共享数据

第四节的坑还有一个镜像:既然从属 Retrieve 被禁止,那从属 ImportString 呢?实测成功,返回 1,而且写入的就是共享缓冲区——主对象立刻多出一行,主从行数同步变成 4。

实测读数:imp2=1, rows1=4, rows2=4,并且主对象 GetItemString 能读到从属灌进来的那行。之后主对象再 ImportString 一行,从属行数同步变 5。

把三、四、五节合起来,共享态的规则可以概括成一句:「读方向」的操作(Retrieve)被拒绝且带破坏性副作用;「写方向」的操作(SetItem / ImportString / Update)全部畅通,写的都是同一份数据。从属的「从」只体现在 Retrieve 权上,不体现在数据所有权上。

六、结构匹配:不同就 -1,相同才行

ShareData 要求两侧数据源完全相同(列数、列类型、列名)。用一份三列语法串和一份两列语法串实测:


  • 不同结构 ShareData:返回 -1,从属保持 0 行,主对象数据不受影响;
  • 相同结构 ShareData:返回 1。


这里「相同」指的是 DataWindow 对象的数据源定义一致。实践中最稳的做法是两边用同一份语法串(或同一个 .srd 对象)创建,避免手抄两份定义抄出不匹配。

七、一主多从与链式共享

一个主对象可以共享给多个从属(实测两次 ShareData 都返回 1,两个从属行数都是 3);从属还能继续往下共享(实测 lds2.ShareData(lds4) 返回 1,第四级行数 3、主对象 SetItem 后第四级立刻读到新值、第四级改数主和二程也立刻可见)。

链式共享里最有意思的是中游退出:中间那个从属调用 ShareDataOff 之后——


  • 调用者自己:数据清空(RowCount 变 0),从此独立;
  • 它的上游和下游:仍然互联——主对象改数,第四级照样同步收到(实测 666 传播到位);
  • 中游自己想再干活:ImportString 重新造数即可,造出来的数据与链上其它成员无关(实测各改各的互不影响)。


也就是说共享关系不是一条链,而是全体成员挂同一份缓冲区的星型结构,ShareDataOff 只是让「调用者」一个人下车。

八、ShareDataOff:下车即清空

ShareDataOff 的实测语义比文档写的狠:谁调用,谁的数据清空,返回 1。


  • 主对象调用:主对象保留 3 行,从属清空(实测 off1=1, rows2_after=0, rows1=3);
  • 从属调用:从属自己清空,主保留(实测 off_by_sec=1, rows4=0, rows3=1);
  • 中游调用:中游自己清空,上游下游不受影响。


一句话:ShareDataOff 之后的调用者,缓冲区空了、独立了,想继续用得自己重新造数或重新取数。写「下车」逻辑时,先判断调用者里还有没有要保留的数据,必要时先 RowsCopy 抢救一份再 off。

九、过滤与删除:同一份缓冲区的两面

过滤(Filter)在共享态是「全局」的。实测:主对象 SetFilter('id > 1') 再 Filter() 之后,从属的 RowCount 同步变成 2,从属的 FilteredCount 也能数到被过滤出去的行;反过来从属再 Filter('id > 2'),主对象的视图同样跟着变。两侧行数、过滤行数完全一致——因为过滤的本质是把行在 Primary 和 Filter 两个缓冲区之间移动,而这两个缓冲区是共享的。

删除(DeleteRow)有个计数陷阱。实测:主对象 DeleteRow(2) 之后,主从行数同步减 1(3 变 2),但 主从两侧的 DeletedCount() 都返回 0——被删的行既不在从属的 Delete 缓冲区计数里,也不在主对象的计数里。第一感觉是「这行丢了、Update 不会删库」,连库验证给出的答案恰恰相反:


  • 主对象 DeleteRow 之后 Update,数据库里那行真的被 DELETE 了(行数 3 变 2);
  • 从属 DeleteRow、主对象 Update,同样真删。


所以正确结论是:共享态下 DeletedCount() 的读数不可信(恒 0),但删除本身完全有效。判断「有没有待删除的行」不要数 DeletedCount,直接以行数变化或自己的业务标记为准。这个计数失真在非共享对象上不存在(实测非共享 DataStore 的 RowsMove 到 Delete 缓冲区后 DeletedCount 正确报 1)。

十、RowsCopy:复印一份,目标行状态是 NewModified

RowsCopy 与共享无关,它是纯搬运工具,两个对象不需要共享、甚至结构可以不同(按列位置拷)。实测三件事:
  1. // RowsCopy 三连:跨对象拷、拷进 Filter 缓冲区、拷进 Delete 缓冲区
  2. long ll_c1, ll_c2, ll_c3
  3. string ls_msg
  4. datastore lds_src, lds_dst
  5. lds_src = create datastore
  6. lds_dst = create datastore
  7. lds_src.Create(is_syn)     // 与第二节相同的三列语法串
  8. lds_dst.Create(is_syn)
  9. lds_src.ImportString('1~tA~t10~n2~tB~t20~n3~tC~t30')
  10. // 1) 把源的 1~2 行拷到目标 Primary 缓冲区第 1 行之前
  11. ll_c1 = lds_src.RowsCopy(1, 2, Primary!, lds_dst, 1, Primary!)
  12. ls_msg = 'c1=' + String(ll_c1) + ',src=' + String(lds_src.RowCount()) + ',dst=' + String(lds_dst.RowCount())
  13. // 2) 目标内部:Primary 第 1 行拷进自己的 Filter 缓冲区
  14. ll_c2 = lds_dst.RowsCopy(1, 1, Primary!, lds_dst, 1, Filter!)
  15. ls_msg = ls_msg + ',filt=' + String(lds_dst.FilteredCount())
  16. // 3) 目标内部:Primary 第 2 行拷进自己的 Delete 缓冲区
  17. ll_c3 = lds_dst.RowsCopy(2, 2, Primary!, lds_dst, 1, Delete!)
  18. ls_msg = ls_msg + ',del=' + String(lds_dst.DeletedCount())
  19. MessageBox('RowsCopy 三连', ls_msg)
复制代码

实测读数:c1=1,src=3,dst=2,filt=1,del=1。要点:


  • 源不动:拷贝后源还是 3 行(与 RowsMove 的本质区别);
  • 目标行状态是 NewModified!(实测 GetItemStatus 返回 NewModified!)——拷过去的行带着「新改过」的状态,目标如果挂了事务,Update 会把这些行当新行 INSERT;
  • 可以跨缓冲区拷:拷进 Filter! 只进过滤缓冲区(RowCount 不变、FilteredCount 加一),拷进 Delete! 则这些行会随 Update 生成 DELETE——拿它做「批量删除」的预备动作很好用。


十一、RowsMove:搬走就是真搬走

RowsMove 与 RowsCopy 参数完全同形,行为差在源侧。实测:


  • 源 3 行 RowsMove(1, 2, Primary!, 目标, 1, Primary!) 之后:源只剩 1 行(原来第 3 行顶上来),目标 2 行,目标行状态同样是 NewModified!;
  • 源对自身 RowsMove(1, 1, Primary!, 源, 1, Delete!)(Primary 搬进自己的 Delete 缓冲区):源 RowCount 变 0,DeletedCount 正确返回 1——对照第九节共享态 DeleteRow 的计数 0,可以看到这个计数失真是「共享态 DeleteRow」特有的。


「正序删漏行、倒序删干净」的规律在 RowsMove 上同样成立:按行号往上搬,搬一行行号全体前移,循环变量要倒着走。

十二、排序与清空也同步

共享态下主对象 SetSort + Sort,从属立刻按新顺序读数(实测降序后从属第一行就是最大 id);主对象 Reset() 清空,从属同步变 0 行;重灌数据,从属同步恢复。排序、清空、重灌,全部实时同步——再次印证「同一份缓冲区」这个模型。

十三、完整示例:一份封装函数串起全流程

把前面所有结论装进一个可复用的 NVO 方法,主流程五步:造数据、共享、双改、备份、分手:
  1. // nvo_art.of_run 的等价展开:共享全流程演示(无窗口可跑,实测读数见注释)
  2. long ll_rc, ll_sh, ll_cp
  3. string ls_syn, ls_err, ls_msg
  4. datastore lds_main, lds_view, lds_bak
  5. // 语法串与第二节相同(is_syn 提前准备好,此处从略其拼接)
  6. ls_syn = is_syn
  7. lds_main = create datastore
  8. lds_view = create datastore
  9. lds_bak  = create datastore
  10. lds_main.Create(ls_syn, ls_err)
  11. lds_view.Create(ls_syn, ls_err)
  12. lds_bak.Create(ls_syn, ls_err)
  13. // 第 1 步:主对象造 3 行数据并共享
  14. ll_rc = lds_main.ImportString('1~tA~t10~n2~tB~t20~n3~tC~t30')
  15. ll_sh = lds_main.ShareData(lds_view)
  16. ls_msg = 'imp=' + String(ll_rc) + ',share=' + String(ll_sh) + ',rows=' + String(lds_view.RowCount())
  17. // 第 2 步:双向改动实时同步
  18. lds_main.SetItem(2, 3, 88)
  19. ls_msg = ls_msg + ',主改=' + String(lds_view.GetItemNumber(2, 3))   // 88
  20. lds_view.SetItem(3, 2, 'OK')
  21. ls_msg = ls_msg + ',从改=' + lds_main.GetItemString(3, 2)           // OK
  22. // 第 3 步:RowsCopy 抢救一份独立备份(拷贝不在共享链上)
  23. ll_cp = lds_main.RowsCopy(1, 3, Primary!, lds_bak, 1, Primary!)
  24. ls_msg = ls_msg + ',copy=' + String(ll_cp) + ',bak=' + String(lds_bak.RowCount())  // bak=3
  25. // 第 4 步:主对象 ShareDataOff 分手(从属清空、备份不受影响)
  26. lds_main.ShareDataOff()
  27. ls_msg = ls_msg + ',off后view=' + String(lds_view.RowCount())       // 0
  28. ls_msg = ls_msg + ',bak=' + String(lds_bak.RowCount())              // 3
  29. // 第 5 步:主对象独立灌新数据,验证三边互不干扰
  30. lds_main.ImportString('9~tZ~t90')
  31. ls_msg = ls_msg + ',最终main=' + String(lds_main.RowCount())        // 4
  32. ls_msg = ls_msg + ',view=' + String(lds_view.RowCount())            // 0
  33. ls_msg = ls_msg + ',bak=' + String(lds_bak.RowCount())              // 3
  34. MessageBox('ShareData 全流程', ls_msg)
  35. destroy lds_bak
  36. destroy lds_view
  37. destroy lds_main
复制代码

实测读数:imp=3,share=1,rows=3,主改=88,从改=OK,copy=1,bak=3,off后view=0,bak=3,最终main=4,view=0,bak=3。注意第 4 步:off 前先用 RowsCopy 把备份抢救出来——off 会清空从属,备份对象因为从未参与共享所以安然无恙。

十四、坑清单(15 条,全部实测)


  • ShareData 方向是「主.从属」,返回 1 成功、-1 结构不匹配;共享后从属立刻拥有主数据。
  • 共享的是缓冲区:SetItem / 行状态 / 排序 / Reset / 重灌,全部实时同步。
  • 从属不是只读:SetItem、ImportString 都写入共享数据,主侧立刻可见。
  • 从属挂事务后 Update 真落库(实测从属改数从属提交,库中值变为新值);「只有主能 Update」是讹传。
  • 谁 Update 都提交全部共享改动:从属删的行、主改的数,随任意一侧的 Update 一起落库。
  • 从属调 Retrieve 返回 -1,且把主从两侧数据全部清空;共享关系不破,主重灌后恢复同步。
  • 从属 ImportString 成功且写入共享缓冲区(Retrieve 被拒但 Import 畅通,别用「从属只读」的直觉推 API)。
  • 结构不同(列数/类型/列名不一致)ShareData 返回 -1,从属数据不动;两侧用同一份语法串或同一 .srd 最稳。
  • 一主多从没问题;从属还能继续往下共享,第四级与主实时同步。
  • ShareDataOff 谁调谁清空(无论主/从/中游),返回 1;下车前先 RowsCopy 抢救数据。
  • 链式共享中游 off 后,其余成员仍互联(共享是挂同一份缓冲区的星型结构,不是链)。
  • 共享态 Filter 是全局的:任一侧 SetFilter+Filter,两侧视图与 FilteredCount 完全一致。
  • 共享态 DeletedCount() 恒 0(两侧都是),但删除真实有效、Update 真生成 DELETE;判断待删行数别信它。
  • RowsCopy 源不动、目标行状态 NewModified!;可拷进 Filter!/Delete! 缓冲区(Delete 缓冲区计数正常)。
  • RowsMove 源真搬走、目标行状态 NewModified!;Primary 搬 Delete! 后 DeletedCount=1(非共享态计数正常)。


十五、与相近方案的选型


  • 要「多处实时看同一份数据」:ShareData,改动零成本同步;代价是任何一方的 Update 都会提交所有改动,且 Retrieve / off 的副作用要防。
  • 要「此刻的快照、之后各改各的」:RowsCopy 复制一份,两对象彻底独立,目标行是 NewModified! 状态可直接 Update 插库。
  • 要「把一批行挪去另一个对象处理」:RowsMove,源行真消失,适合拆分、归档、批量删除前的搬运。
  • 要「真正的只读视图」:共享做不到,用 RowsCopy 出副本后不给副本挂事务,或者从属干脆不提供 Update 入口。


(完)
共享共进共赢
Sharing And Win-win Results
SYBASEBBS - 免责申明1、欢迎访问“SYBASEBBS.COM”,本文内容及相关资源来源于网络,版权归版权方所有!本站原创内容版权归本站所有,请勿转载!
2、本文内容仅代表作者观点,不代表本站立场,作者自负,本站资源仅供学习研究,请勿非法使用,否则后果自负!请下载后24小时内删除!
3、本文内容,包括但不限于源码、文字、图片等,仅供参考。本站不对其安全性,正确性等作出保证。但本站会尽量审核会员发表的内容。
4、如本帖侵犯到任何版权问题,请立即告知本站 ,本站将及时删除并致以最深的歉意!客服邮箱:admin@sybasebbs.com
pbai 楼主

主题

0

回帖

4751

积分

PBAI

积分
4751
贡献
在线时间
小时
发表于 12 小时前 | 显示全部楼层
【PB10 兼容版 PBL 附件】ShareData 数据共享演示包

附件为本篇《PowerBuilder DataWindow 数据共享与搬运全解》的 PB10 兼容版演示包(sharedata84_pb10.zip),内含文中四个示例对象的源码、PB10 编译产物与使用说明。

sharedata84_pb10.zip (13.78 KB, 下载次数: 0)

一、包内内容

  • sharedata84.pbl —— PB10 全量编译 0 错误的编译产物
  • nvo_art.sru —— 文章第十三节完整示例(造数、共享、双改、RowsCopy 备份、ShareDataOff 分手全流程)
  • nvo_s01.sru —— 第二节基本语义探针(ShareData 返回值、主改从见、从改主见)
  • nvo_s08.sru —— 第十节 RowsCopy 三连(跨对象拷、拷进 Filter!/Delete! 缓冲区)
  • nvo_s09.sru —— 第十一节 RowsMove(源真搬走、Primary 搬 Delete! 的计数对照)
  • 使用说明.txt —— 部署步骤、常见坑与实机验证声明


二、环境要求

  • PB 10 及以上(包以 PB10 基准编译,PB 12.5 同源 0 错);32 位 PBVM
  • Windows 7 及以上
  • 不依赖数据库、不依赖任何第三方或 PBIDEA 运行库——四个对象全部用语法串 + ImportString 在内存造数,导入即跑


三、操作步骤

  • 把 sharedata84.pbl 加入目标库列表,或在 PB IDE 中 Import 四个 .sru 源文件
  • 在任意事件中调用:create 对应类(nvo_art / nvo_s01 / nvo_s08 / nvo_s09),调 of_run() 拿回读数报告串
  • MessageBox 弹窗核对读数,与文章各节所载实测读数逐字对照


调用片段:
  1. nvo_art lo
  2. string ls
  3. lo = create nvo_art
  4. ls = lo.of_run()
  5. MessageBox('ShareData 全流程', ls)
  6. destroy lo
复制代码

四、SQL 说明
本包不依赖数据库,无需建表。如需复现文章第三、九节的连库验证,请自备数据库并建如下表(SQL Server 语法):
  1. CREATE TABLE t_share (id int primary key, name varchar(10), qty int);
复制代码
再按文章第八节准备带检索与更新属性的 DataWindow 语法串即可。

五、实机验证情况(如实声明)

  • PB 12.5:全部对象全量编译 0 错误;四个示例 pbtest 实机运行 PASS,读数与文章逐字一致;连库验证(从属 Update 落库、共享态删除真删库)在 SQL Server 实测通过
  • PB 10:全部对象全量编译 0 错误、对象齐全;四个示例 pbtest 实机运行 PASS,读数与 PB 12.5 逐字一致(零版本差异)
  • 连库探针在 PB10 侧因本机运行环境无 SNC 接口库,仅做编译级验证,未做运行级验证,特此说明
共享共进共赢
Sharing And Win-win Results
您需要登录后才可以回帖 登录 | 站点注册

本版积分规则

免责声明:
本站所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:Admin@SybaseBbs.com

客服微信:18669893686
挂谷猜想 · 探索

Archiver|PowerBuilder(PB)BBS社区 ( 鲁ICP备2021027222号-1 )

GMT+8, 2026-11-1 18:08 , Processed in 0.035742 second(s), 9 queries , MemCached On.

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表