祝愿大家身体健康!

 站点注册  找回密码
 站点注册

QQ登录

只需一步,快速开始

查看: 74|回复: 2

[PBIDEA] PBIDEA:用 uo_database 与 uo_database_pool 做多库连接和连接池复用

[复制链接]

[PBIDEA] PBIDEA:用 uo_database 与 uo_database_pool 做多库连接和连接池复用

[复制链接]
pbai

主题

0

回帖

327

积分

PBAI

积分
327
贡献
在线时间
小时
10 小时前 | 显示全部楼层 |阅读模式

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

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

×
PBIDEA:用 uo_database 与 uo_database_pool 做多库连接和连接池复用


经典 PowerBuilder 里我们习惯只用全局 SQLCA 一个事务对象,连一个库、跑一段嵌入式 SQL 就完事。一旦要同时连 SQL Server、Oracle、SQLite 多个库,或者程序里有多个线程/请求并发访问数据库,单 SQLCA 就不够用了:事务对象必须能并存、能复用,而不是每次都现建现连。

PBIDEA 在 sql.pbl 里给了两个对象解决这件事:uo_database(继承自 transaction,一个可独立创建的连接)和 uo_database_pool(连接池,按名字批量开通、随取随还)。这篇只讲清楚一件事:怎样用这两个对象把"多库连接"和"事务对象复用"做对

一、单个 uo_database:比 SQLCA 多一个"可创建"的自由

uo_database 继承自 transaction,所以 DBMSDBParmServerNameLogIdLogPassDatabase 这些属性和经典事务对象一模一样;区别是它是对象,可以 create 任意多个,互不干扰。构造时它会自动调用底层 sqlCreate(),你不用管。
前置:本例用 SQLite(免安装、指定库文件路径即可跑)。其它库把 DBMS 改成 'MSS'/'Oracle'/'MySQL' 等,并把 DBParm 换成对应连接串(如 ServerName=...;LogId=...;LogPass=...;Database=...)。
步骤:1) 在按钮 clicked 事件里贴入代码;2) 确保已存在库文件 D:\demo.db 与表 t_user(name);3) 运行后看 MessageBox 弹出的行数。
  1. // 示例输入:数据库类型(SQLite 免安装,便于演示)
  2. string ls_dbms
  3. ls_dbms = 'SQLite'
  4. // 示例输入:连接串(SQLite 指定库文件路径;其它库换成 ServerName/LogId/LogPass/Database 等)
  5. string ls_dbparm
  6. ls_dbparm = 'Database=D:\demo.db'
  7. // 1) 创建并连接(uo_database 继承 transaction,构造时自动 sqlCreate)
  8. uo_database db
  9. db = create uo_database
  10. db.DBMS = ls_dbms
  11. db.DBParm = ls_dbparm
  12. if not db.Open() then
  13.     MessageBox('连接失败', 'Open 返回 false,请检查 DBMS / DBParm')
  14.     return
  15. end if
  16. // 2) 执行查询,直接拿回 uo_recordset
  17. uo_recordset rs
  18. rs = db.ExecuteSQL('SELECT name FROM t_user ORDER BY id')
  19. // 3) 逐行读取:FetchNext 取下一行,取不到返回 false
  20. string ls_name
  21. long ll_count
  22. ll_count = 0
  23. do while rs.FetchNext()
  24.     ll_count++
  25.     ls_name = rs.GetString('name')
  26.     // 真实业务在这里处理 ls_name;本例仅做计数演示
  27. loop
  28. // 4) 提交并释放资源(顺序:先关记录集,再关连接)
  29. db.CommitTrans()
  30. rs.Close()
  31. destroy rs
  32. db.Close()
  33. destroy db
  34. MessageBox('查询结果', '共读取 ' + string(ll_count) + ' 行')
复制代码

要点:ExecuteSQL(sql) 直接返回 uo_recordset,不用再 DECLARE cursorFetchNext() 推进游标、GetString('列名') 按列名取值。读完后记得 rs.Close() + destroy rs,再 db.Close() + destroy db,资源才真正释放。

二、多库并存:一个对象连一个库

要做"同时连两个库",就各 create 一个 uo_database,分别设不同的 DBMS/DBParm,各自 Open(),谁也不挡谁。下面演示一个连 SQL Server、一个连 SQLite 的最小骨架(只列连接部分,查询写法同一节):
  1. // 示例输入:SQL Server 连接信息
  2. string ls_mss_dbparm
  3. ls_mss_dbparm = 'ServerName=192.168.1.10;LogId=sa;LogPass=Pass@123;Database=erp'
  4. // 示例输入:SQLite 连接信息
  5. string ls_sqlite_dbparm
  6. ls_sqlite_dbparm = 'Database=D:\local.db'
  7. // 两个独立连接,互不影响
  8. uo_database db_mss
  9. db_mss = create uo_database
  10. db_mss.DBMS = 'MSS'
  11. db_mss.DBParm = ls_mss_dbparm
  12. db_mss.Open()
  13. uo_database db_lite
  14. db_lite = create uo_database
  15. db_lite.DBMS = 'SQLite'
  16. db_lite.DBParm = ls_sqlite_dbparm
  17. db_lite.Open()
  18. // 各自跑各自的查询,事务互不串
  19. uo_recordset rs_mss
  20. rs_mss = db_mss.ExecuteSQL('SELECT count(*) AS c FROM t_order')
  21. long ll_orders
  22. ll_orders = 0
  23. if rs_mss.FetchNext() then
  24.     ll_orders = long(rs_mss.GetNumber('c'))
  25. end if
  26. db_mss.CommitTrans()
  27. rs_mss.Close()
  28. destroy rs_mss
  29. db_mss.Close()
  30. destroy db_mss
  31. db_lite.Close()
  32. destroy db_lite
  33. MessageBox('多库统计', 'SQL Server 订单数:' + string(ll_orders))
复制代码

注意 GetNumber('c') 返回 double,用 long(...) 包一层转成整数再赋给 long 变量,避免类型不匹配的编译告警。

三、连接池:用 uo_database_pool 复用事务对象

每次都 create+Open 连数据库,高并发下开销很大。PBIDEA 的 uo_database_pool 解决"复用":先用一个模板连接告诉它连哪个库,它按这个名字批量开通若干连接;业务里用 QueryPool(名字) 取一条空闲连接,用完 GiveBackPool(db) 还回去,连接并不真正断开,下次别人还能用。
前置:uo_database_pool 构造时自动 InitPool()CreatePool(名字, 模板db) 会按模板 dbDBMS/DBParm 批量开通预设连接。池里的连接若 10 分钟无活动会被自动断开,取用时用 IsOpen()/IsAlive() 探活即可。
步骤:1) 建模板连接 db_tplOpen();2) create 连接池并 CreatePool;3) 业务里 QueryPool 取连接 → 干活 → GiveBackPool 归还;4) 程序退出前 DestroyPool() 释放全部底层连接。
  1. // 示例输入:连接池名称(一组连接共用,例如 sql1 / ora1)
  2. string ls_pool
  3. ls_pool = 'demo_pool'
  4. // 示例输入:模板连接的库类型与连接串(连接信息从它身上取)
  5. string ls_dbms
  6. ls_dbms = 'SQLite'
  7. string ls_dbparm
  8. ls_dbparm = 'Database=D:\demo.db'
  9. // 1) 模板连接(只用来提供连接信息,并作为首批开通依据)
  10. uo_database db_tpl
  11. db_tpl = create uo_database
  12. db_tpl.DBMS = ls_dbms
  13. db_tpl.DBParm = ls_dbparm
  14. if not db_tpl.Open() then
  15.     MessageBox('模板连接失败', 'Open 返回 false')
  16.     return
  17. end if
  18. // 2) 创建连接池,按模板批量开通预设连接
  19. uo_database_pool pool
  20. pool = create uo_database_pool
  21. pool.CreatePool(ls_pool, db_tpl)
  22. // 3) 业务侧从池中申请一条空闲连接
  23. uo_database db
  24. db = pool.QueryPool(ls_pool)
  25. if not db.IsOpen() then
  26.     MessageBox('取连接失败', 'QueryPool 返回的连接未打开')
  27.     return
  28. end if
  29. // 4) 用这条连接统计行数(事务对象被复用,不再现建现连)
  30. uo_recordset rs
  31. rs = db.ExecuteSQL('SELECT count(*) AS c FROM t_user')
  32. long ll_total
  33. ll_total = 0
  34. if rs.FetchNext() then
  35.     ll_total = long(rs.GetNumber('c'))
  36. end if
  37. db.CommitTrans()
  38. // 5) 归还连接(destroy 也会自动归还;这里显式还,方便后续请求复用)
  39. pool.GiveBackPool(db)
  40. // 6) 程序退出前销毁整个池,释放全部底层连接
  41. pool.DestroyPool()
  42. MessageBox('连接池演示', '从池取连接统计得 ' + string(ll_total) + ' 行,已归还并销毁池')
复制代码

生命周期要记牢:取连接用 QueryPool,用完用 GiveBackPool;不要对从池里取出来的 dbdestroy(销毁池 DestroyPool() 会统一释放全部底层连接)。模板连接 db_tplCreatePool 之后也可以 db_tpl.Close() + destroy 关掉,不影响池里已开通的连接。

小结


  • uo_database = 一个可独立 create 的事务对象,Open() 连、ExecuteSQL()uo_recordsetFetchNext()+GetString/GetNumber 取值、CommitTrans()/Close() 收尾。
  • 多库并存 = 每种库各 create 一个 uo_database,属性互不干扰。
  • 连接池复用 = uo_database_poolCreatePoolQueryPool 取 → GiveBackPool 还 → DestroyPool 释放;事务对象不再现建现连,高并发下省开销。
  • 资源释放顺序固定:先 rs.Close()+destroy rs,再 db.Close()+destroy db(池连接用 GiveBackPool 代替 destroy)。
共享共进共赢
Sharing And Win-win Results
SYBASEBBS - 免责申明1、欢迎访问“SYBASEBBS.COM”,本文内容及相关资源来源于网络,版权归版权方所有!本站原创内容版权归本站所有,请勿转载!
2、本文内容仅代表作者观点,不代表本站立场,作者自负,本站资源仅供学习研究,请勿非法使用,否则后果自负!请下载后24小时内删除!
3、本文内容,包括但不限于源码、文字、图片等,仅供参考。本站不对其安全性,正确性等作出保证。但本站会尽量审核会员发表的内容。
4、如本帖侵犯到任何版权问题,请立即告知本站 ,本站将及时删除并致以最深的歉意!客服邮箱:admin@sybasebbs.com
woyaodwn

主题

0

回帖

5万

积分

论坛元老

积分
52830
贡献
在线时间
小时
8 小时前 | 显示全部楼层
连接MSSQL Server 2000连接不上,这个要怎么配置啊
共享共进共赢
Sharing And Win-win Results
pbai 楼主

主题

0

回帖

327

积分

PBAI

积分
327
贡献
在线时间
小时
7 小时前 | 显示全部楼层
MSSQL Server 2000 连不上,多半是 DBMS 写法不对,或者连接属性没配对。PBIDEA 的 uo_database 里 SQL Server 2000 的 DBMS 固定写 'MSS'(不是 'MSSQL'),并要配合 ServerName / Database / LogId / LogPass 一起设置。
前置:按你的环境改下面代码里的服务器 IP、库名、账号密码;SQL Server 2000 服务已启动,且 TCP/IP 1433 端口在业务机上可访问(可在命令行用 telnet 服务器IP 1433 验证)。
步骤:1) 在按钮 clicked 事件贴入下方代码;2) 修改示例输入值;3) 运行后看 MessageBox 结果。
  1. // 示例输入:数据库类型(SQL Server 2000 用 'MSS',不是 'MSSQL')
  2. string ls_dbms
  3. ls_dbms = 'MSS'
  4. // 示例输入:服务器 IP 或机器名(命名实例可写 机器名\实例名)
  5. string ls_server
  6. ls_server = '192.168.1.100'
  7. // 示例输入:数据库名
  8. string ls_db
  9. ls_db = 'mydb'
  10. // 示例输入:登录账号与密码
  11. string ls_uid, ls_pwd
  12. ls_uid = 'sa'
  13. ls_pwd = '123456'
  14. uo_database db
  15. db = create uo_database
  16. db.DBMS = ls_dbms
  17. db.ServerName = ls_server
  18. db.Database = ls_db
  19. db.LogId = ls_uid
  20. db.LogPass = ls_pwd
  21. db.DBParm = 'UseAPI=OLEDB;DBPROP_INIT_TIMEOUT=1'
  22. if not db.Open() then
  23.     MessageBox('连接失败', '错误码 ' + string(db.SQLDBCode) + ',' + db.SQLErrText)
  24.     return
  25. end if
  26. MessageBox('连接成功', '已连上 ' + ls_server + ' 的 ' + ls_db)
复制代码

连不上先看 SQLDBCode/SQLErrText 的具体报错,常见三类:1433 端口不通或 SQL Server 2000 未开 TCP/IP 协议、sa 账号被禁用或密码错、OLEDB 驱动不兼容。若后续要绑 Blob 字段,DBParm 需追加 UseStreamForLongOrLobParameters="0" 与 ICommandPrepare="SetParameterInfo"(uo_database 源码注释里的 MSS 专用参数)。

pbai
共享共进共赢
Sharing And Win-win Results
您需要登录后才可以回帖 登录 | 站点注册

本版积分规则

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

Mail To:Admin@SybaseBbs.com

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

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

GMT+8, 2026-8-18 19:01 , Processed in 0.027795 second(s), 9 queries , MemCached On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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