调用Persist()前缓存变更已存入数据库问题求助
问题分析
从你的描述和代码来看,核心问题在于在CRCaseClass_RowUpdated事件中直接调用caseContract.Insert(c)会触发Acumatica内置的缓存持久化逻辑,导致变更在你自定义的Persist()方法执行前就被写入数据库,同时缓存被自动清空,使得你重写的Persist()无法按预期处理数据。
Acumatica的缓存机制会在数据操作(如Insert/Update)后,在当前的事务周期内自动跟踪变更,如果你直接操作关联缓存,这些变更会被纳入默认的持久化流程,跳过你自定义的逻辑。
解决方案
我们需要调整数据处理的时机:在Row事件中临时存储变更,直到自定义Persist方法执行时再统一处理缓存和数据库操作。具体步骤如下:
1. 在Graph中添加临时存储集合
首先,在你的Contract Template页面对应的Graph类中,定义一个私有集合来临时保存CaseContract的变更,避免直接操作caseContract缓存:
private List<CaseContract> _pendingCaseContracts = new List<CaseContract>();
2. 修改RowUpdated事件逻辑
在CRCaseClass_RowUpdated事件中,不再直接插入到caseContract缓存,而是将变更记录添加到临时集合中,同时处理新增和更新的场景:
protected void CRCaseClass_RowUpdated(PXCache sender, PXRowUpdatedEventArgs e) { CRCaseClass newrow = (CRCaseClass)e.Row; CRCaseClass oldrow = (CRCaseClass)e.OldRow; ContractTemplate currentContract = contracts.Current; if (currentContract == null) return; CRCaseClassExt newrowExt = PXCache<CRCaseClass>.GetExtension<CRCaseClassExt>(newrow); // 查找临时集合中是否已有该CaseClass的记录 var existingRecord = _pendingCaseContracts.FirstOrDefault(cc => cc.ContractID == currentContract.ContractID && cc.CaseClassID == newrow.CaseClassID); if (existingRecord != null) { // 更新已有记录的Active状态 existingRecord.Active = newrowExt.Check.Value; } else { // 添加新的变更记录 _pendingCaseContracts.Add(new CaseContract { CaseClassID = newrow.CaseClassID, ContractID = currentContract.ContractID, Active = newrowExt.Check.Value }); } }
注意:如果需要处理行删除的场景,可以额外添加
CRCaseClass_RowDeleted事件,将对应记录标记为待删除或从临时集合移除。
3. 重写Persist方法,统一处理变更
修改你的Persist()重写方法,先处理临时集合中的记录,同步到caseContract缓存,再执行默认的持久化逻辑:
[PXOverride] public void Persist() { ContractTemplate currentContract = contracts.Current; if (currentContract == null || !_pendingCaseContracts.Any()) { // 无变更时直接执行默认持久化 Base.Persist(); return; } foreach (var pending in _pendingCaseContracts) { // 查询数据库中是否已有该关联记录 var existingDbRecord = PXSelect<CaseContract, Where<CaseContract.contractID, Equal<Required<CaseContract.contractID>>, And<CaseContract.caseClassID, Equal<Required<CaseContract.caseClassID>>>>> .Select(Base, currentContract.ContractID, pending.CaseClassID) .FirstOrDefault(); if (existingDbRecord != null) { // 更新已有记录 existingDbRecord.Active = pending.Active; caseContract.Update(existingDbRecord); } else { // 插入新记录 caseContract.Insert(pending); } } // 清空临时集合,避免重复处理 _pendingCaseContracts.Clear(); // 执行默认持久化逻辑,将缓存变更写入数据库 Base.Persist(); }
关键说明
- 临时集合的作用:避免直接操作caseContract缓存,防止Acumatica自动触发提前持久化,确保所有变更都能被自定义Persist方法统一处理。
- 缓存操作时机:在Persist方法中统一处理缓存的Insert/Update,确保变更在你控制的时机被提交到数据库。
- 事务一致性:Acumatica的Base.Persist()会处理整个事务,确保所有变更(包括合同模板和CaseContract)要么全部成功,要么全部回滚,保证数据一致性。
内容的提问来源于stack exchange,提问作者Prathyusha
相关产品推荐
相关产品推荐

