Acumatica升级2021 R2后新增客户默认LocationID返回负值问题
版本变更说明
2021 R2(Build 21.206.0024)确实调整了CustomerMaint业务图的默认位置记录持久化时序,是原有代码失效的核心原因:
- 2021 R2之前的版本:新建客户过程中,框架会提前为默认Location生成已持久化的正整数主键,Persist方法触发前即可从缓存读取到有效ID
- 2021 R2及之后版本:默认Location记录与客户主记录保持一致的持久化时序,在整个Persist事务提交到数据库完成前,记录仅保留框架分配的缓存临时标识——也就是捕获到的负值,该值仅在当前会话缓存内生效,数据库无对应记录,直接用该值查询
Location表必然返回null。
有效LocationID获取方案
不要在系统原生持久化动作执行前读取缓存中的LocationID做数据库查询,以下两种方案可稳定适配新版本逻辑:
方案1:调整Persist重写逻辑的执行顺序
将自定义的Tax Zone匹配逻辑移到原生persistAction委托执行完成后,此时主记录与默认Location均已完成落库,LocationID会替换为正式正整数值,可正常查询。参考修正代码:
public void Persist(Action persistAction) { // 优先执行系统原生持久化逻辑,完成主数据落库 persistAction?.Invoke(); // 持久化完成后读取默认位置,此时LocationID为正式有效值 var cachedLocation = Base.GetExtension<CustomerMaint.DefLocationExt>(); var loc = cachedLocation.DefLocation.Current; var dbLocation = SelectFrom<Location> .Where<Location.locationID.IsEqual<@P.AsInt>> .View.ReadOnly.Select(Base, loc.LocationID) .TopFirst; // 此处补充自定义Tax Zone匹配、回写逻辑 }
如果Tax Zone计算结果需要回写到客户或位置记录,自定义逻辑处理完成后需调用对应缓存的Update方法,再触发一次持久化避免数据丢失。
方案2:采用事件订阅替代Persist重写
按照Acumatica框架开发最佳实践,不建议直接重写Persist方法,可订阅Location表的RowPersisted事件,在默认位置完成落库后触发自定义逻辑,时序稳定性更高,不受后续版本持久化时序调整影响:
protected virtual void Location_RowPersisted(PXCache sender, PXRowPersistedEventArgs e) { if (e.TranStatus != PXTranStatus.Open || e.Row is not Location loc) return; // 仅匹配客户默认位置的新增场景 if (loc.IsDefault != true || e.Operation != PXDBOperation.Insert) return; // 此处loc.LocationID为正式有效值,可直接执行数据库查询、Tax Zone匹配逻辑 }
通用规则:Acumatica框架中所有未完成持久化的缓存记录,自增主键字段出现负值属于正常的临时占位逻辑,不要尝试手动转换该值或绕过缓存查询,必须等待对应记录完成数据库提交后再读取主键,才能获得可用于数据库查询的有效取值。
内容的提问来源于stack exchange,提问作者MarkJoel60
相关产品推荐
相关产品推荐

