06.03.2014, 17:25 | #1 |
Участник
|
PurchLine update conflict ??
Мне нужно присвоить новые значения полю PurchLine.PurchReceivedNow , код приблизительно такой:
X++: ttsBegin; while select forupdate purchLine order by Confirmeddlv where purchLine.PurchId == purchId && purchLine.ItemId == itemId && purchLine.PurchStatus == PurchStatus::Backorder && (!purchLine.IsDeleted) exists join InventDim where lalala { // purchLine.reread(); if (receivedQty >= purchLine.RemainPurchPhysical) { purchLine.PurchReceivedNow = purchLine.RemainPurchPhysical; receivedQty -= purchLine.RemainPurchPhysical; } else { purchLine.PurchReceivedNow = receivedQty; receivedQty = 0; } purchLine.setInventReceivedNow(); purchLine.Tax1099Amount = 0; purchLine.Tax1099StateAmount = 0; if (purchLine.validateWrite()) { purchLine.update(); } else { throw error('my error'); } } Ax2012 R2 Последний раз редактировалось IKA; 06.03.2014 в 17:35. |
|
06.03.2014, 18:52 | #2 |
Сенбернар
|
Уточните, пожалуйста, что там подразумевается под lalala. И зачем - exists join ?
---- Предварительный диагноз : - по exists join вы одну и ту же PurchLine находите не один, а больше раз. - поскольку весь цикл - внутри транзакции - при попытке повторно изменить запись (без reread()) - происходит тот самый update conflict Вот как-то так
__________________
Best Regards, Roman Последний раз редактировалось RVS; 06.03.2014 в 18:55. |
|
06.03.2014, 18:58 | #3 |
Участник
|
1) каким образом exists может приводить к дупликатам???????
2) дело точно не в inventDim , тк в дебаггере видно. что разные записи purchLine выбираются |
|
06.03.2014, 19:21 | #4 |
Сенбернар
|
Условие "lalala" расшифруйте - тогда объясню, каким. Если может, конечно ))
Пока не вижу условия - могу только предполагать. Потоому и написал - "предварительный" диагноз )
__________________
Best Regards, Roman |
|
06.03.2014, 19:55 | #5 |
Moderator
|
Попробуйте включить трассировку SQL и посмотреть (по сохраненному стеку вызовов) из какого куска кода реально идет обновление purchLine. Ваш purchLine.update() втихаря порождает вызов inventUpd_estimated, в котором много чего интересного происходит. Есть шансы что из за кастомизаций или из за какого-нить неаккуратно отключенного регионального функционала, этот код находит еще одну копию того же самого purchLine, меняет ее и обновляет. Когда после этого доходит дело до обновления в самом purchLine.update(), система начинает ругаться, потому что номер версии записи в переданном буфере и номер версии записи в БД - не совпадают.
|
|
|
За это сообщение автора поблагодарили: MikeR (10), S.Kuskov (2). |
06.03.2014, 22:11 | #6 |
Участник
|
Нет тогда бы purchLine.reread() не помог бы избежать конфликта, т.к. стоит в самом начале итерации. Обновляется другая запись, не та (или не только та) запись которая выбрана на текущей итерации, но тоже присутствующая в выборке.
|
|
|
За это сообщение автора поблагодарили: IKA (1). |
07.03.2014, 12:06 | #7 |
Сенбернар
|
А почему бы не сделать "естественным образом"? Вот так, например :
X++: ttsBegin; while select forupdate purchLine order by Confirmeddlv where purchLine.PurchId == purchId && purchLine.ItemId == itemId && purchLine.PurchStatus == PurchStatus::Backorder && ! purchLine.IsDeleted join inventDim where inventDim.InventDimId == purchLine.InventDimId && lalala { // Что-то делаем с purchLine purchLine.update(); } IKA, напишите, как решилось, пожалуйста. Случай странный, ИМХО )
__________________
Best Regards, Roman |
|
07.03.2014, 13:23 | #8 |
Участник
|
А у вас случаем не активен чек активировать управление изменениями в параметрах модуля закупок и источников ?
Просто в стандарте в методе update строки покупки вшит код, который в некоторых случая при обновлении данных по одной строке запускает массовую обработку по всем строкам текущего заказа см. PurchLineType\updatePurchTable (строка с VersioningPurchaseOrder\change, там кстати вызов идет через doUpdate других строк). Цитата:
А почему бы не сделать "естественным образом"?
__________________
Sergey Nefedov |
|
|
За это сообщение автора поблагодарили: RVS (1), IKA (1). |
07.03.2014, 14:36 | #9 |
Участник
|
Если кому интересно, я накопала в чем проблема, вот ток как лечить - ума не приложу, тк мне кажется, это баг
Все дело в коде класса VersioningPurchaseOrder метод archivePurchLine, в самом конце вызывыается такое дело : X++: purchLine.skipDataMethods(true); purchLine.skipDatabaseLog(true); update_recordset purchLine setting IsModified = NoYes::No where purchLine.PurchId == purchTable.PurchId && purchLine.IsModified && purchLine.InventTransId != skipInventTransId; Дело в том,что мне кажется, это куски того, что должно вызываться при галке, упомянутой SRF , но 1) у нас она не стоит 2) в коде нет никаких проверок на какие-либо парметры и настройки (ну или я не вижу). Стек вызовов у меня такой X++: [s] \Classes\VersioningPurchaseOrder\archivePurchLine 99 [s] \Classes\VersioningPurchaseOrder\archiveCurrentVersion 28 [s] \Classes\VersioningDocument\change 40 [s] \Classes\VersioningPurchaseOrder\change 26 [s] \Classes\PurchLineType\updatePurchTable 11 [s] \Classes\PurchLineType\update 79 [s] \Classes\PurchLineType_Purch\update 38 [s] \Data Dictionary\Tables\PurchLine\Methods\update 17 Вопрос вечный : Кто виноват и что теперь делать??? Последний раз редактировалось IKA; 07.03.2014 в 14:53. |
|
|
За это сообщение автора поблагодарили: Мартынов Дмитрий (1). |
07.03.2014, 14:41 | #10 |
Участник
|
А чем не устраивает исходное решение - дергать внутри цикла purchLine.reread()?
|
|
07.03.2014, 14:42 | #11 |
Участник
|
На всяк случай, значения параметров:
purchLineType.update(dropInvent, false, updateOrderLineOfDeliverySchedule) - здесь dropInvent = false, updateOrderLineOfDeliverySchedule = true В purchLineType_Purch -> update вызов super(_dropInvent, _forceInterCompanyMirror, _updateOrderLineOfDeliverySchedule); , тут _dropInvent = false _forceInterCompanyMirror = false _updateOrderLineOfDeliverySchedule = true Дальше все вызывается без параметров |
|
07.03.2014, 14:51 | #12 |
Участник
|
Да, этот вызов я и имел ввиду. Он также может вызываться если у закупки статус Подтверждено, у вас в покупке этот статус, если да, попробуйте на какой нибудь у которой этот статус другой. Т.е. массово обновлять строки в покупке лучше до того момента пока эта покупка имеет статус до подтверждено. В стандарте есть ряд ключевых полей при изменении которых этот статус сбрасывается всегда, и потом требуется повторное подтверждение.
__________________
Sergey Nefedov Последний раз редактировалось SRF; 07.03.2014 в 15:04. |
|
07.03.2014, 14:51 | #13 |
Участник
|
2gl00mie: Смысл писать в while select forupdate, если записи могут быть обновлены втихоря другой транзакцией?
Последний раз редактировалось IKA; 07.03.2014 в 14:56. |
|
07.03.2014, 15:09 | #14 |
Участник
|
Во-первых, в 2012-й для PurchLine по умолчанию включена OCC, так что forupdate и так не накладывает по умолчанию никаких блокировок в БД, во-вторых, с точки зрения СУБД это не другая транзакция, а ваша же собственная, в которой вы лопатите строки закупки. Просто в данной ситуации, образно говоря, правая рука не знает, что делает левая, но зато есть очень простое решение - перечитать запись перед обработкой, так почему бы этим решением не воспользоваться?
|
|
07.03.2014, 15:53 | #15 |
Участник
|
Я бы всё-таки предпочел выяснить, в какой момент запись обновляется извне, чтобы убедиться, что без reread никак, и спать спокойно. Хотя это может занять какое-то время.
Однажды с таким столкнулся, и исправил косяк в том, другом методе, так что reread не понадобился. |
|
07.03.2014, 16:39 | #16 |
Участник
|
Выше приведен стек вызовов, показывающий, в какой момент запись обновляется "извне"
|
|
|
За это сообщение автора поблагодарили: Stitch_MS (1). |
15.01.2016, 13:39 | #17 |
Участник
|
Подниму тему.
проблема в том, что не работает purchLine.skipDataMethods(true); X++: purchLine.skipDataMethods(true); purchLine.skipDatabaseLog(true); update_recordset purchLine setting IsModified = NoYes::No where purchLine.PurchId == purchTable.PurchId && purchLine.IsModified && purchLine.InventTransId != skipInventTransId; а вот в связи с чем он может не работать? |
|
15.01.2016, 14:16 | #18 |
MCITP
|
Цитата:
Сообщение от under_construction
Подниму тему.
проблема в том, что не работает purchLine.skipDataMethods(true); X++: purchLine.skipDataMethods(true); purchLine.skipDatabaseLog(true); update_recordset purchLine setting IsModified = NoYes::No where purchLine.PurchId == purchTable.PurchId && purchLine.IsModified && purchLine.InventTransId != skipInventTransId; а вот в связи с чем он может не работать? Если речь про 2012, то AOSAuthorization Property на таблице у вас случайно не настроен? Тогда ещё .skipAosValidation() нужен будет
__________________
Zhirenkov Vitaly |
|
15.01.2016, 16:26 | #19 |
Участник
|
Еще skipEvents() стоит попробовать - вдруг кто уведомления себе настроил.
|
|
|
За это сообщение автора поблагодарили: MikeR (5). |
15.01.2016, 18:11 | #20 |
Участник
|
|
|
Теги |
ax2012, ax2012r2 |
|
|