|
02.09.2021, 08:47 | #1 |
Участник
|
как обойти ошибку - запись не выбиралась для обновления
Привет всем.
При выполнении такого джоба: X++: static void job123(Args _args) { ... void updateFieldValue(Common _common, FieldId _fieldId, anytype _value) { ... try { ttsBegin; _common.selectForUpdate(true); _common.(_fieldId) = _value; _common.doUpdate(); ttsCommit; } catch { ttsAbort; } ... } ... ; ... updateFieldValue(APMParameters::find(), fieldnum(APMParameters, Field1), valueField1); ... } генерируется ошибка: Цитата:
Невозможно отредактировать запись в Параметры (APMParameters).
Операция не может быть завершена, так как запись не выбиралась для обновления. Используйте TTSBEGIN/TTSCOMMIT наряду с выражением FORUPDATE. Попытка изменения записи в таблице "APMParameters", которая не выбрана для изменения (RecId = 5637144576). [W-0108] (S)\Classes\xRecord\doUpdate (C)\Jobs\job123 - line 77 Мне получилось ее обойти так: X++: static void job123(Args _args) { ... void updateFieldValue(Common _common, FieldId _fieldId, anytype _value) { ... try { //ttsBegin; // <-- убираем _common.selectForUpdate(true); _common.(_fieldId) = _value; _common.doUpdate(); //ttsCommit; // <-- убираем } catch { ttsAbort; } ... } ... ; ... ttsBegin; // <-- добавляем updateFieldValue(APMParameters::find(), fieldnum(APMParameters, Field1), valueField1); ttsCommit; // <-- добавляем ... } Вопросы: 1. возможно как то обойти данную ошибку но оставив ttsBegin/ttsCommit в методе updateFieldValue ? 2. Заметил что такая ошибка генерируется только для изменения данных у этой таблицы - APMParameters. Если такое же выполнять для других таблиц, например: RassetParameters, CompanyInfo таких ошибок нет. Не подскажете почему для одних таблиц нет ошибки а для APMParameters ошибка при вызове doUpdate()? Последний раз редактировалось oleggy; 02.09.2021 в 08:52. |
|
02.09.2021, 09:38 | #2 |
Administrator
|
Метод _common.selectForUpdate(true); должен выполняться до выборки данных.
Т.е. сначала _common.selectForUpdate(true); А потом - select * from common. Приведенный пример - излюбленный способ тех разработчиков, которым не хочется делать лишний select, а хочется уже после выборки либо обновлять, либо не обновлять запись (сам таким когда-то был - знаю). База данных так не работает. Ей нужно знать до выборки - блокировать ли записи или нет на обновление. Поэтому правильное решение - перестроить код так, чтобы вызов метода selectForUpdate был бы ДО оператора выборки данных. Конструкция, приведенная у Вас - может работать (ядро АХ все-таки старается) - но могут быть разные глюки - либо с блокировками при многопользовательской работе, либо с ошибками как у Вас, либо еще какие-то ошибки
__________________
Возможно сделать все. Вопрос времени Последний раз редактировалось sukhanchik; 02.09.2021 в 09:41. |
|
|
За это сообщение автора поблагодарили: SRF (1), oleggy (1). |
02.09.2021, 10:03 | #3 |
Участник
|
А как сделать select для common таблицы?
Если известна recId записи и tableId этой таблицы. Подскажите подход. К сожалению не сработало. |
|
02.09.2021, 10:09 | #4 |
Участник
|
|
|
02.09.2021, 10:21 | #5 |
Участник
|
Да, такая же ошибка, я проверил, для таблиц с OCCEnabled = No, reread не помогает, для них надо делать новый запрос в БД, видимо текущий курсор изменить уже нельзя, а нужно создавать новый.
__________________
Sergey Nefedov |
|
02.09.2021, 10:33 | #6 |
Участник
|
Получилось только так:
X++: static void job123(Args _args) { ... void updateFieldValue(Common _common, FieldId _fieldId, anytype _value) { DictField dictField; DictTable dictTable = new DictTable(_common.tableId); Common common; ; ... try { ttsBegin; common = dictTable.makeRecord(); common.selectForUpdate(true); select common where common.RecId == _common.RecId; common.(_fieldId) = _value; ttsCommit; } catch { ttsAbort; } ... } ... ; ... updateFieldValue(APMParameters::find(), fieldnum(APMParameters, Field1), valueField1); ... } |
|
|
За это сообщение автора поблагодарили: sukhanchik (2), SRF (1). |
02.09.2021, 10:12 | #7 |
Участник
|
А попробуйте вместо reread сделать
select _common where _common.recid == _common.recId;
__________________
Sergey Nefedov |
|
02.09.2021, 10:41 | #8 |
Участник
|
Цитата:
Потом я создал локальную common и написал так. X++: select common where common.TableId == _common.TableId && common.RecId == _common.RecId; |
|
02.09.2021, 10:56 | #9 |
Участник
|
Ну надежды на то что сработает условие _common.recid == _common.recId нет и не может быть. Это как масло масленое. А то что common нужно инициализировать (типизировать) перед использованием в принципе логично. Иначе система не будет знать к какой таблице делать запрос и дополнительно условие по TableId здесь не спасает (в SQL нет такого понятия как запрос сразу ко всем таблицам).
Не понятно почему не сработал reread |
|
|
За это сообщение автора поблагодарили: SRF (2). |
02.09.2021, 11:26 | #10 |
Administrator
|
Цитата:
X++: TableId myTableId; RecId myRecId; DictTable dictTable = new DictTable(myTableId); Common myRecord; myRecord = dictTable.myRecord(); select myRecord where myRecord.RecId == myRecID; X++: TableId myTableId; RecId myRecId; Query query; QueryBuildDataSource qbds; QueryRun qr; query = new Query(); qbds = query.addDataSource(myTableId); qbds.addRange(fieldnum(Common, RecId)).value(queryvalue(myRecId)); qr = new QueryRun(query); if (qr.next()) { myRecord = qr.getNo(1); }
__________________
Возможно сделать все. Вопрос времени Последний раз редактировалось sukhanchik; 02.09.2021 в 11:33. |
|
02.09.2021, 09:57 | #11 |
Участник
|
Посмотрите по ключевому слову OCCEnabled, https://docs.microsoft.com/en-us/dyn...rrency-control
Для табличек у которых OCCEnabled = yes, ваш код будет работать, для тех у которых No не будет, им нужна явная выборка в транзакции. Можно сделать примерно так, но получите дополнительное чтение в БД. X++: ttsbegin; _common.selectForUpdate(true); _common.reread(); _common.(_fieldId) = _value; _common.doUpdate(); ttscommit;
__________________
Sergey Nefedov Последний раз редактировалось SRF; 02.09.2021 в 10:03. |
|
|
За это сообщение автора поблагодарили: EVGL (5), sukhanchik (2), S.Kuskov (2), oleggy (1). |
02.09.2021, 18:51 | #12 |
Участник
|
Интересно, не встречал проблем с работой reread (ну конечно, если к этому моменту запись не удалена).
Там в вызове, случайно, нет какого-либо фиксирования, типа common.data() ? |
|
|
|