马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?站点注册
×
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 = 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——你就再也不会被“明明改了却没保存”“明明删了库里还有”这类问题困扰了。 |