15.12.2010, 11:54 | #1 |
Участник
|
Common.reread() - альтернатива для findRecId?
Хочу поинтересоваться у общественности - на сколько "правомочно" использовать следующий приём?
X++: static void JobTestCommonReread(Args _args) { InventTable InventTable; InventTable InventTable2; RecId RecId; ; select firstonly InventTable; RecId = InventTable.RecId; InventTable2.RecId = RecId; InventTable2.reread(); info(InventTable2.ItemId); } X++: // myTable не выбирался для обновления, но нам понадобилось изменить в нём данные myTable.selectForUpdate(true); ttsbegin; myTable.reread(); ... myTable.update(); ttscommit; myTable.selectForUpdate(false); } |
|
15.12.2010, 12:01 | #2 |
Участник
|
Продолжил эксперименты с джобом JobTestCommonReread. Метод reread() в комбинации с методом clear() ведёт себя не столь очевидно.
X++: static void JobTestCommonReread(Args _args) { InventTable InventTable, InventTable2; RecId RecId; ; select firstonly InventTable; RecId = InventTable.RecId; InventTable2.RecId = RecId; InventTable2.reread(); info(InventTable2.ItemId); InventTable2.clear(); // ??? InventTable2.RecId = RecId; InventTable2.reread(); info(InventTable2.ItemId); // ??? } |
|
15.12.2010, 12:03 | #3 |
Ищущий знания...
|
не знаю на сколько правомочно, но то что очень удобно это точно!
когда не знаешь будешь изменять записи в таблице или нет, и обновление выполняется при определенных условиях. пользуюсь этим регулярно, и пока никаких проблем не было З.Ы. единственный нюанс, если все изменения критичны для целостности данных, то лучше конечно выбрать запись для апдейта заранее, независимо от того изменится запись в будущем или нет.
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
|
За это сообщение автора поблагодарили: S.Kuskov (1). |
15.12.2010, 12:10 | #4 |
Ищущий знания...
|
Цитата:
reread() - это не аналог find(), а метод для перезагрузки курсора из базы.
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
15.12.2010, 12:14 | #5 |
Ищущий знания...
|
кстати про findRecId.
я в одно время создал статический метод Find() в классе SysDictTable. в этом методе выполняется поиск по переданному RecId в таблице, Id которой так же передается в метод. Сделал это для того, что бы не заморачиваться написанием методов FindRecId на каждой таблице. Ведь поиск по RecId не так часто делается, да и пользоваться им нужно с умом, ведь не всегда есть индекс по RecId.
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
15.12.2010, 12:39 | #6 |
Участник
|
Но можно попытаться явно присвоить RecId. В моём первом примере курсор InventTable2 не был проинициалицирован, но reread() сработал, если же курсор стереть явно, при помощи clear, то reread перестаёт работать (второй пример). В чём принципиальная разница между непроинициализированным курсором и курсором после clear()?
|
|
15.12.2010, 12:48 | #7 |
Участник
|
Поэкспериментировав, пришел к выводу, что нужно обнулить ссылку на область памяти, на которую ссылается табличная переменная. В итоге гарантированно "перевыбрать" запись при помощи reread можно так:
X++: static void JobTestCommonReread(Args _args) { InventTable InventTable, InventTable2; RecId RecId; ; select firstonly InventTable; RecId = InventTable.RecId; InventTable2.RecId = RecId; InventTable2.reread(); info(InventTable2.ItemId); InventTable2.clear(); inventTable2 = null; InventTable2.RecId = RecId; InventTable2.reread(); info(InventTable2.ItemId); }
__________________
С уважением, Александр. Последний раз редактировалось samolalex; 15.12.2010 в 12:51. |
|
|
За это сообщение автора поблагодарили: lev (1), S.Kuskov (1). |
15.12.2010, 12:51 | #8 |
Ищущий знания...
|
Цитата:
Сообщение от S.Kuskov
Но можно попытаться явно присвоить RecId. В моём первом примере курсор InventTable2 не был проинициалицирован, но reread() сработал, если же курсор стереть явно, при помощи clear, то reread перестаёт работать (второй пример). В чём принципиальная разница между непроинициализированным курсором и курсором после clear()?
про clear() я думаю все понятно, и он делает то что я написал выше. скорее встает вопрос, а как же работает метод reread() ??? получается ему для выбора кроме RecId нужно ещё что то, что вычищается после использования метода clear().
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
|
За это сообщение автора поблагодарили: samolalex (1). |
15.12.2010, 12:52 | #9 |
Ищущий знания...
|
Тоже подумал про NULL, но меня опередили
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
15.12.2010, 12:53 | #10 |
Участник
|
тоже так думаю
__________________
С уважением, Александр. |
|
15.12.2010, 13:05 | #11 |
Участник
|
|
|
|
За это сообщение автора поблагодарили: lev (2), samolalex (1). |
15.12.2010, 13:06 | #12 |
Ищущий знания...
|
ага именно! не правильно выразился
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
15.12.2010, 13:50 | #13 |
Administrator
|
Цитата:
Попробуйте выполнить такой код. В нем reread честно отработает (вспоминаем, что в БД индекс состоит из двух полей - RecID и dataareaid, т.о. выбрать запись просто по RecId система не может - ей нужен еще dataareaid): X++: static void Job1(Args _args) { InventTable inventTable; ; inventTable.clear(); breakpoint; inventTable = null; inventTable.(fieldnum(InventTable, dataAreaId)) = 'dat'; inventTable.RecId = 5637147343; inventTable.reread(); breakpoint; }
__________________
Возможно сделать все. Вопрос времени |
|
15.12.2010, 13:59 | #14 |
Ищущий знания...
|
Цитата:
Сообщение от sukhanchik
Достаточно посмотреть в отладчик, чтобы понять, что clear() устанавливает все поля в их "нулевое" или "начальное" состояние. В частности, попутно устанавливаются и системные поля (например, код компании).
Попробуйте выполнить такой код. В нем reread честно отработает (вспоминаем, что в БД индекс состоит из двух полей - RecID и dataareaid, т.о. выбрать запись просто по RecId система не может - ей нужен еще dataareaid): X++: static void Job1(Args _args) { InventTable inventTable; ; inventTable.clear(); breakpoint; inventTable = null; inventTable.(fieldnum(InventTable, dataAreaId)) = 'dat'; inventTable.RecId = 5637147343; inventTable.reread(); breakpoint; } если посмотреть в отладчике, после выполнения метода clear() поле DataAreaId остается со значением компании (то значение, которое было в выбранном курсоре). Затем ещё присваивается значение полю RecId. Получается перед выполнением метода reread() у нас и так заполнены два нужных поля. кстати, тут уже писалось, что если обнулить память для таблицы (выполнить присвоение переменной NULL), то reread() нормально работает. а в Вашем примере в начале вызывается clear(), а потом обнуляется переменная, поэтому все нормально отрабатывает
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
15.12.2010, 14:00 | #15 |
Участник
|
dataAreaId - это первое, что я проверил . sukhanchik, на какой версии вы эксперементировали? На AX2009 clear не очищает поле dataAreaId, он принудительно заполняет его активной компанией.
И да, как правильно заметил lev, что будет если из вашего примера убрать строку "inventTable = null"? P.S.: Демонстрация того, что при clear значение поля DataAreaId не просто не очищается, но даже принудительно меняется на значение текущей компании X++: static void JobTestClearDataAreaId(Args _args) { InventTable InventTable; ; InventTable.(fieldnum(InventTable, dataAreaId)) = "XXX"; info(InventTable.dataAreaId); InventTable.clear(); info(InventTable.dataAreaId); } Последний раз редактировалось S.Kuskov; 15.12.2010 в 14:11. |
|
15.12.2010, 14:02 | #16 |
Ищущий знания...
|
вот так:
X++: static void Job1(Args _args) { InventTable inventTable; ; inventTable.clear(); breakpoint; //inventTable = null; inventTable.(fieldnum(InventTable, dataAreaId)) = 'dat'; inventTable.RecId = 5637147343; inventTable.reread(); breakpoint; }
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
15.12.2010, 14:03 | #17 |
Ищущий знания...
|
на Ах 3.0 поле dataAreaId тоже не вычищается.
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
15.12.2010, 14:13 | #18 |
Administrator
|
Цитата:
А... сорри, не так понял. Я то думал - что не хватает курсору после null-а. И решил что dataareaid. А речь шла про то, что clear() не позволяет делать reread(). Хотя... у меня вариант от lev отработал также (т.е. запись все равно выбралась). Проверял на другом RecId (исключил вариант кеша)
__________________
Возможно сделать все. Вопрос времени |
|
15.12.2010, 14:18 | #19 |
Administrator
|
Кстати и на DAX2009 RU5 также отработало как и на 4.0 SP2
__________________
Возможно сделать все. Вопрос времени |
|
15.12.2010, 14:29 | #20 |
Участник
|
Странно, правда я проверял на AX2009SP1 без ролапов. Может ли ещё кто-нибудь проверить?
К стати, "InventTable = NULL" так же как и clear() сбрасывет dataAreaId к значению текущей компании X++: static void JobTestClearDataAreaId_2(Args _args) { InventTable InventTable; ; InventTable.(fieldnum(InventTable, dataAreaId)) = "XXX"; InventTable = NULL; info(InventTable.dataAreaId); } |
|