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]