Цитата:
Сообщение от
fed
В общем - дело давнее: Насколько я помню, в стандартном сводном DAX2009 была бага, связанная с кэшированием чистых потребностей. Когда происходит вызов reqTrans.update() туда как второй (насколько я помню) параметр передается ссылка на класс ReqTransCache, где кэш с чистыми потребностями хранится. И после обновления, reqTrans.update() складывает в reqTransCache обновленную копию записи.
При этом где-то как раз в недрах методов deleteExplosionCoverage и deleteExplosionCoverageTrans этот второй параметр не передается и в reqTransCache остаются необновленные данные, при использовании которых и случается updateConflict. (На самом деле - там не update conflict в чистом виде, а просто попытка записать в БД устаревшую копию записи, с неверным recVersion). Я это лечил простым способом - при вызове цепочки deleteExplosion() я новым параметром передавал ReqTransCache и дальше передавал его глубже в reqTrans.update() (и возможно в reqTrans.delete() и reqTrans.insert() - я уже не помню есть там такой параметр или нет). После того как я это сделал, проблема вылечилась и система у клиента уже 12 лет работает.
P.S. Поправка - судя по коду D365FO передается не reqTransCache, а reqPlanData. Но из reqPlanData внутри update вынимается ReqTransCache и туда обновленные данные складываются. Но в целом - подход к решению это не меняет. Над убедится что из deleteExplosion* в метод update передается ссылка на правильный класс.
Хмм, спасибо огромное, но судя по всему всё так и передается
В ReqTrans.update()
X++:
public server void update(ReqPlanData _reqPlanData = null,
boolean _reduceCovQty = true)
{
ReqTransCache reqTransCache = _reqPlanData ? _reqPlanData.reqTransCache() : null;
а после super()
X++:
if (reqTransCache)
reqTransCache.update(this);
Методы deleteExplosionCoverage(Trans) просто протаскивают через себя необязательный параметр
X++:
server void deleteExplosionCoverageTrans(ReqPlanData _reqPlanData = null)
Ну а по стеку эта цепочка начинается в ReqCalc.deleteItemRequirement(), но там идет передача
X++:
if (reqTrans.isDerivedDemand())
{
// reqTrans has to be updated but it could be it has been derived deleted by the previous record in this select statement
// we need to ensure the record still exists
if ( reqTransCache.exists(reqTrans)
|| ReqTrans::findRecId(reqTrans.RecId).RecId)
{
reqTrans.CovQty = 0;
reqTrans.update(reqPlanData);
}
}
else
if (reqTrans.isPlannedOrder())
{
setupDim = reqPlanData.newReqSetupDim(_setup,reqTrans.CovInventDimId);
if (reqPlanData.mustKeepPlannedOrder(setupDim,reqTrans,setApprovedPlannedOrder))
{
reqTrans.CovQty = 0;
reqTrans.update(reqPlanData);
}
else
{
reqTrans.deleteExplosionCoverage(reqPlanData);
doDelete = true;
}
}
else
doDelete = true;
Не понятно когда reqPlanData пустым передается