使用TcxGrid搭建CRUD表单,TClientDataSet执行ApplyUpdates(0)后修改未同步到数据库
问题原因与解决步骤
错误根因分析
你遇到的两个报错直接对应两个核心问题:ORA-01722: invalid number是字段类型不匹配导致:ClientDataSet中ID_UC/ID_SUI的字段类型和Oracle表中对应字段的类型不一致,或者生成的更新SQL错误给数字类型加了引号Unable to find record. No key specified是没有给ClientDataSet指定联合主键,TDataSetProvider无法定位数据库中需要更新/删除的记录
第一步:配置ClientDataSet联合主键
设计期操作:- 双击
cdBraUCFormatoSUI打开字段编辑器,右键添加所有永久字段,确认ID_UC/ID_SUI的字段类型和Oracle表中一致(Oracle NUMBER类型对应DelphiftInteger/ftLargeint,不要设为ftString) - 打开ClientDataSet的
Indexes属性,新建一个索引,添加ID_UC和ID_SUI两个字段,将索引的Primary属性设为True
- 双击
第二步:调整TDataSetProvider配置
- 将
UpdateMode属性从upWhereAll改为upWhereKeyOnly,仅用主键定位记录,避免全字段匹配带来的类型兼容问题 - 确认
poAutoRefresh属性开启,提交后自动刷新本地数据集
- 将
第三步:修正提交逻辑
你当前的代码缺少提交后缓存清理逻辑,且直接在事件中提交可能触发状态冲突,调整代码如下:procedure TForm3.cdBraUCFormatoSUIAfterDelete(DataSet: TDataSet); begin ApplyCDSUpdates; end; procedure TForm3.cdBraUCFormatoSUIAfterPost(DataSet: TDataSet); begin ApplyCDSUpdates; end; procedure TForm3.FormCreate(Sender: TObject); begin cdBraUCFormatoSUI.Open; end; // 新增独立的提交方法 procedure TForm3.ApplyCDSUpdates; var errCount: Integer; begin if cdBraUCFormatoSUI.ChangeCount = 0 then Exit; try errCount := cdBraUCFormatoSUI.ApplyUpdates(0); if errCount = 0 then begin cdBraUCFormatoSUI.CommitUpdates; // 清理本地变更缓存,必须添加 // 若数据库连接未开自动提交,取消下方注释 // SQLQuery1.Connection.Commit; end; except on E: Exception do begin ShowMessage('提交失败:' + E.Message); cdBraUCFormatoSUI.CancelUpdates; // 出错回滚本地变更 end; end; end;可选优化建议
不建议在AfterDelete/AfterPost中实时提交,可新增单独的提交按钮,用户编辑完成后统一提交,避免频繁操作数据库、减少异常概率。
内容的提问来源于stack exchange,提问作者BaldwinIV
相关产品推荐
相关产品推荐

