Acumatica技术问询:修改POLine承诺日期时SOLine视图始终返回空值的问题排查
问题:POLine承诺日期变更时无法更新SOLine自定义字段,视图返回空值
我现在遇到一个问题:当POLine的PromisedDate字段发生变更时,我想要同步更新关联SOLine上的自定义字段UsrPOPromisedDate。我写了一段Acumatica图扩展代码,但不管怎么试,SalesOrderLine视图始终返回空值。奇怪的是,把代码里的BQL转换成T-SQL执行时,能得到预期的关联SOLine记录。有没有大佬能帮我看看问题出在哪?
我的代码如下:
using PX.Data; using PX.KWW.MyProject.DAC; using PX.Objects.PO; using PX.Objects.SO; namespace MyProject.Graph { public class POOrderEntryExt : PXGraphExtension<POOrderEntry> { public PXSelectJoin< SOLine, InnerJoin<SOLineSplit, On<SOLineSplit.orderType, Equal<SOLine.orderType>, And<SOLineSplit.orderNbr, Equal<SOLine.orderNbr>, And<SOLineSplit.lineNbr, Equal<SOLine.lineNbr>>>>>, Where<SOLineSplit.pOType, Equal<Current<POLine.orderType>>, And<SOLineSplit.pONbr, Equal<Current<POLine.orderNbr>>, And<SOLineSplit.pOLineNbr, Equal<Current<POLine.lineNbr>>>>> > SalesOrderLine; protected virtual void _(Events.FieldUpdated<POLine, POLine.promisedDate> eventHandler, PXFieldUpdated baseHandler) { baseHandler?.Invoke(eventHandler.Cache, eventHandler.Args); POLine pOLine = eventHandler.Row; if (pOLine is null) return; SOLine sOLine = SalesOrderLine.Current; SOLineExtension sOLineExtension = sOLine.GetExtension<SOLineExtension>(); if (sOLine is null || sOLineExtension is null) return; sOLineExtension.UsrPOPromisedDate = pOLine.PromisedDate; SalesOrderLine.Update(sOLine); } } }
问题分析与解决方案
嗨,我来帮你捋捋这个问题!核心原因其实很简单:你的视图没有主动执行查询操作。
在Acumatica里,PXSelectJoin定义的视图并不会自动去数据库捞数据,除非你主动调用Select()或者SelectSingle()方法。你现在直接取SalesOrderLine.Current,它只会返回之前已经加载到视图缓存里的记录——而在FieldUpdated事件触发时,这个视图压根没执行过查询,所以自然返回空值。而你用T-SQL能查到结果,说明BQL的逻辑是对的,只是代码里少了触发查询的步骤。
修复后的代码
我帮你调整了代码,主要加了主动查询的逻辑,同时考虑了可能存在多条关联SOLine的情况:
using PX.Data; using PX.KWW.MyProject.DAC; using PX.Objects.PO; using PX.Objects.SO; namespace MyProject.Graph { public class POOrderEntryExt : PXGraphExtension<POOrderEntry> { public PXSelectJoin< SOLine, InnerJoin<SOLineSplit, On<SOLineSplit.orderType, Equal<SOLine.orderType>, And<SOLineSplit.orderNbr, Equal<SOLine.orderNbr>, And<SOLineSplit.lineNbr, Equal<SOLine.lineNbr>>>>>, Where<SOLineSplit.pOType, Equal<Current<POLine.orderType>>, And<SOLineSplit.pONbr, Equal<Current<POLine.orderNbr>>, And<SOLineSplit.pOLineNbr, Equal<Current<POLine.lineNbr>>>>> > SalesOrderLine; protected virtual void _(Events.FieldUpdated<POLine, POLine.promisedDate> eventHandler, PXFieldUpdated baseHandler) { baseHandler?.Invoke(eventHandler.Cache, eventHandler.Args); POLine pOLine = eventHandler.Row; if (pOLine is null) return; // 主动执行查询,遍历所有关联的SOLine记录 foreach (SOLine sOLine in SalesOrderLine.Select()) { SOLineExtension sOLineExtension = sOLine.GetExtension<SOLineExtension>(); if (sOLineExtension == null) continue; sOLineExtension.UsrPOPromisedDate = pOLine.PromisedDate; // 直接更新SOLine缓存,确保变更生效 Base.Caches<SOLine>().Update(sOLine); } } } }
几点额外说明
- 用
Select()触发查询:SalesOrderLine.Select()会执行你定义的BQL,从数据库获取符合条件的SOLine记录。 - 遍历处理所有结果:虽然大部分情况下一个POLine只会关联一个SOLine,但用
foreach遍历能避免遗漏特殊情况。 - 直接更新缓存:用
Base.Caches<SOLine>().Update(sOLine)比视图的Update方法更直接,能确保变更被正确写入Acumatica的缓存体系,后续保存时会同步到数据库。
这样修改后,应该就能正常更新SOLine的自定义字段啦!
内容的提问来源于stack exchange,提问作者Jeremy Hodge




