05.06.2018, 08:08 | #1 |
Участник
|
CustTrans невозможно обновить
В CustTrans добавлены 2 поля.
Почему-то некоторые записи не возможно обновить. X++: static void fillCustTrans(Args _args) { #avifiles CustInvoiceJour CustInvoiceJour; CustTrans custTrans; SysOperationProgress progress; int i,j; ; select count(recid) from custTrans where custTrans.Invoice != "" ; i = custTrans.RecId; progress = SysOperationProgress::newGeneral(#aviupdate, "Update", i); while select AmountCur10,AmountCur18,recid,Invoice,AccountNum,TransDate from custTrans where custTrans.Invoice != "" // && custTrans.RecId == 5638268785 { j++; progress.setText(strfmt("%1 from %2", j, i)); progress.incCount(); select firstonly TaxAmount10, TaxAmountStandart from CustInvoiceJour where CustInvoiceJour.invoiceId == custTrans.Invoice && CustInvoiceJour.InvoiceAccount == custTrans.AccountNum && CustInvoiceJour.InvoiceDate == custTrans.TransDate; custTrans.selectForUpdate(true); ttsbegin;//custTrans.ttsbegin(); custTrans.AmountCur10 = CustInvoiceJour.TaxAmount10; custTrans.AmountCur18 = CustInvoiceJour.TaxAmountStandart; try { custTrans.doupdate(); // ошибка возникает здесь } catch { info(strfmt("%1",custTrans.RecId)); ttsabort; continue; } ttscommit;//custTrans.ttscommit(); } } Невозможно отредактировать запись в Проводки по клиенту (CustTrans). Возник конфликт обновления из-за того, что другой пользовательский процесс выполняет удаление записи или изменение одного или нескольких полей в записи. Причем всегда по одному и тому же recId. База тестовая, на ней никто не работает. Что можно сделать такое, чтобы обновить всю таблицу? Последний раз редактировалось iiipoizone; 05.06.2018 в 08:11. |
|
05.06.2018, 09:55 | #2 |
Участник
|
Кто ж вас так код форматировать учил?
Попробуйте X++: while select forUpdate custTrans where custTrans.Invoice { } AX нужно RecVersion, без него она не может понять обновляете ли вы то что выбрали ранее, а вы его не выбираете... Последний раз редактировалось skuull; 05.06.2018 в 10:04. |
|
|
За это сообщение автора поблагодарили: S.Kuskov (5), iiipoizone (1). |
05.06.2018, 10:33 | #3 |
Участник
|
Или после custTrans.selectForUpdate(true) нужно повторно перечитать запись custTrans.reread();
|
|
|
За это сообщение автора поблагодарили: iiipoizone (1). |
05.06.2018, 11:21 | #4 |
Участник
|
Это будет работать, но это тупо. Мы выбираем список полей, а потом реридом выбираем все поля еще раз. 2 запроса к БД, в чем смысл?
Последний раз редактировалось skuull; 05.06.2018 в 11:57. |
|
05.06.2018, 12:44 | #5 |
Участник
|
Цитата:
Однако код совершенно не пригоден с точки зрения производительности:
__________________
// no comments |
|
05.06.2018, 13:25 | #6 |
Участник
|
Не некоторые, а все, что попали в фильтр по условию.
__________________
// no comments |
|
05.06.2018, 13:35 | #7 |
Участник
|
Цитата:
Ведь если ставить forupdate в запросе, то и транзакцию тогда открывать до цикла? См. также forUpdate перед ttsbegin Модификация огромного количества (сотни тысяч) записей в Axapta 3.0 SP4 Последний раз редактировалось S.Kuskov; 05.06.2018 в 13:49. |
|
05.06.2018, 13:41 | #8 |
Участник
|
Цитата:
Причина 1: Это фича (особенность) хранения данных MS SQL. 1. Если в запросе явным образом не указана опция Order By, то, в общем случае, порядок следования записей в выборке будет произвольным Да, как правило, этот порядок будет совпадать с кластерным индексом. Но именно "как правило". Это именно "совпадение". Не гарантия 2. При внесении изменений в данные таблицы возможно (опять же, не обязательно. Возможно) перестроение индексов вообще и кластерных индексов в частности Из этого следует, что, в общем случае, если внутри цикла выполняется изменение данных той таблицы, по которой выборка и выполняется, то возможно, что одна и та же запись таблицы внутри цикла while select может быть выбрана несколько раз Для проверки этого предположения, выведите в infolog значения всех записей, которые попали в выборку и посмотрите, не повторяется ли одно и то же значение RecId несколько раз На самом деле, такая ситуация является скорее исключением, чем правилом. Т.е. случается достаточно редко. Просто это надо иметь в виду. "Лечится" это двумя способами 1. Регулярное обновление (перестроение) индексов базы данных 2. Включение в цикл While select опции order By. Но! Обязательно по тем полям, которые не будет изменяться внутри цикла. В данном случае можно по RecId Причина 2: Запись действительно была обновлена Это зависит от версии Axapta и сделанных изменений. Дело в том, что doUpdate() не гарантирует того, что никакие сопутствующие методы не будут выполнены. Она лишь гарантирует, что не будет выполнен табличный метод Update(). Но изменения в запись могут быть внесены и другими методами. И вот в этом случае изменится значение RecVersion и Axapta посчитает, что запись была изменена другим процессом. В этом случае и требуется перезапрос Reread() Посмотрите, нет ли у Вас на таблице CustTrans каких-либо связанных событий на методе update.
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
|
За это сообщение автора поблагодарили: iiipoizone (1). |
06.06.2018, 07:27 | #9 |
Участник
|
Благодарю всех. надо было в Select добавить поле RecVersion
|
|
|
|