pbai 发表于 6 天前

PowerBuilder DataWindow 三缓冲区详解:Primary / Delete / Filter 各存了什么

本帖最后由 pbai 于 2026-8-14 09:25 编辑

DataWindow 的三个缓冲区:Primary / Delete / Filter


一句话:DataWindow 不是“一张表”,而是三块内存。你改过、删过、过滤掉的数据,各自待在不同的地方,理解它们才能驾驭保存与回滚。


很多初学者以为 DataWindow 就是“从数据库读出来显示的一张表”。其实当你 Retrieve() 之后,DataWindow 在内存里维护了三块独立的缓冲区(buffer),数据的“状态”决定了它会被怎么处理。这三块是:


[*]Primary Buffer(主缓冲):当前显示、参与保存的“主数据”。
[*]Delete Buffer(删除缓冲):被 DeleteRow() 删掉、但还没真正提交到数据库的行。
[*]Filter Buffer(过滤缓冲):被 SetFilter() + Filter() 筛掉、当前不显示的行。


下面把每一块讲清楚,并说明它们如何互相流动。

一、Primary Buffer:你看到的就是它

Retrieve() 取回的数据默认全部进入 Primary Buffer,屏幕上看到的、滚动的、点击编辑的,都是这块里的行。


dw_1.Retrieve()
// 此时所有行都在 Primary Buffer
long ll_rows
ll_rows = dw_1.RowCount()   // 等于 Primary 中的行数


你在界面上修改某单元格,行仍然留在 Primary 里,只是它的行状态变成了“已修改(Modified)”。Update() 时,DataWindow 会扫描 Primary 里“新增/修改”的行,生成对应的 INSERT / UPDATE 语句。

二、Delete Buffer:删除不是真删,是“搬了个家”

调用 DeleteRow() 时,行并没有从内存消失,而是被移动到 Delete Buffer:


dw_1.DeleteRow(ll_row)   // 第 ll_row 行从 Primary 移入 Delete Buffer



[*]屏幕上:这一行立刻消失(不在 Primary 了)。
[*]内存里:它还在 Delete Buffer 中。
[*]数据库里:此时还没动。


只有执行 Update() 并提交(COMMIT)后,Delete Buffer 中的行才会真正生成 DELETE 语句发往数据库。如果中途想反悔:


dw_1.RowsDiscard(ll_row, Primary!, false)   // 彻底丢弃(不进 Delete Buffer)
// 或:不调用 Update,直接重新 Retrieve 即可让删除“白做”



坑:若你已经 Update() 成功并 COMMIT,Delete Buffer 就被清空、无法撤销了。删除前的“后悔药”是未提交前重新 Retrieve。


三、Filter Buffer:筛选掉的行去哪了

SetFilter() + Filter() 并不会删除数据,而是把不满足条件的行从 Primary 搬到 Filter Buffer:


dw_1.SetFilter("salary > 5000")
dw_1.Filter()             // 不满足的行进入 Filter Buffer
// 此时 RowCount() 只统计 Primary 中留下的行



[*]屏幕:只显示满足条件的行。
[*]Filter Buffer:藏着被筛掉的行,它们不参与保存,也不会被 Update() 提交。


想让它们回来?改回宽松的过滤条件再 Filter 一次:


dw_1.SetFilter("")
dw_1.Filter()             // 所有行回到 Primary


四、怎么判断一行“在什么状态”

DataWindow 提供 GetItemStatus() 告诉你某一行/某一列在 Primary 中的状态,SetItemStatus() 可以手动改变它:


// 状态枚举:NotModified! / DataModified! / New! / NewModified!
long ll_status
ll_status = dw_1.GetItemStatus(ll_row, 0, Primary!)   // 0 表示整行
if ll_status = NewModified! then
    // 这是用户新增且改过的行
end if

// 把一行标记为“未修改”,避免被重复 UPDATE
dw_1.SetItemStatus(ll_row, 0, Primary!, NotModified!)


常见状态含义:


[*]NotModified!:取回后没动过。
[*]DataModified!:取回后改过值。
[*]New!:新增但还没填值。
[*]NewModified!:新增且已填值。


五、三者与 Update 的关系(核心)

Update() 到底会提交什么,取决于行在哪个缓冲区 + 什么状态:


缓冲区Update 时的行为
Primary 中 New/NewModified 行生成 INSERT
Primary 中 DataModified 行生成 UPDATE
Delete Buffer 中的行生成 DELETE
Filter Buffer 中的行不参与(不会被保存)
Primary 中 NotModified 行跳过(无变化)


所以一个典型“保存”流程是:


if dw_1.Update() = 1 then
    COMMIT USING SQLCA;
    // 保存成功,各缓冲区按结果收敛
else
    ROLLBACK USING SQLCA;
    // 保存失败,数据仍在内存,可修正后重试
end if


六、一个反直觉的结论


[*]“屏幕上不见了” ≠ “被删了”:可能是被 Filter 到了 Filter Buffer。
[*]“删除了一行” ≠ “数据库少了一行”:那只是进了 Delete Buffer,没 Update()+COMMIT 就还在库里。
[*]想做“所见即所存、不存被筛掉的数据”,就要注意 Filter() 后那些行其实脱离了保存范围。


把这三块缓冲区想成三个抽屉,数据在抽屉之间搬动,Update() 只把对应抽屉里的“变化”翻译成 SQL——你就再也不会被“明明改了却没保存”“明明删了库里还有”这类问题困扰了。
页: [1]
查看完整版本: PowerBuilder DataWindow 三缓冲区详解:Primary / Delete / Filter 各存了什么

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

Mail To:Admin@SybaseBbs.com