|
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:10 | #3 |
Ищущий знания...
|
Цитата:
reread() - это не аналог find(), а метод для перезагрузки курсора из базы.
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
15.12.2010, 12:39 | #4 |
Участник
|
Но можно попытаться явно присвоить RecId. В моём первом примере курсор InventTable2 не был проинициалицирован, но reread() сработал, если же курсор стереть явно, при помощи clear, то reread перестаёт работать (второй пример). В чём принципиальная разница между непроинициализированным курсором и курсором после clear()?
|
|
15.12.2010, 12:48 | #5 |
Участник
|
Поэкспериментировав, пришел к выводу, что нужно обнулить ссылку на область памяти, на которую ссылается табличная переменная. В итоге гарантированно "перевыбрать" запись при помощи 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:52 | #6 |
Ищущий знания...
|
Тоже подумал про NULL, но меня опередили
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
15.12.2010, 12:51 | #7 |
Ищущий знания...
|
Цитата:
Сообщение от S.Kuskov
Но можно попытаться явно присвоить RecId. В моём первом примере курсор InventTable2 не был проинициалицирован, но reread() сработал, если же курсор стереть явно, при помощи clear, то reread перестаёт работать (второй пример). В чём принципиальная разница между непроинициализированным курсором и курсором после clear()?
про clear() я думаю все понятно, и он делает то что я написал выше. скорее встает вопрос, а как же работает метод reread() ??? получается ему для выбора кроме RecId нужно ещё что то, что вычищается после использования метода clear().
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
|
За это сообщение автора поблагодарили: samolalex (1). |
15.12.2010, 12:53 | #8 |
Участник
|
тоже так думаю
__________________
С уважением, Александр. |
|
15.12.2010, 13:05 | #9 |
Участник
|
|
|
|
За это сообщение автора поблагодарили: lev (2), samolalex (1). |
15.12.2010, 12:03 | #10 |
Ищущий знания...
|
не знаю на сколько правомочно, но то что очень удобно это точно!
когда не знаешь будешь изменять записи в таблице или нет, и обновление выполняется при определенных условиях. пользуюсь этим регулярно, и пока никаких проблем не было З.Ы. единственный нюанс, если все изменения критичны для целостности данных, то лучше конечно выбрать запись для апдейта заранее, независимо от того изменится запись в будущем или нет.
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
|
За это сообщение автора поблагодарили: S.Kuskov (1). |
15.12.2010, 12:14 | #11 |
Ищущий знания...
|
кстати про findRecId.
я в одно время создал статический метод Find() в классе SysDictTable. в этом методе выполняется поиск по переданному RecId в таблице, Id которой так же передается в метод. Сделал это для того, что бы не заморачиваться написанием методов FindRecId на каждой таблице. Ведь поиск по RecId не так часто делается, да и пользоваться им нужно с умом, ведь не всегда есть индекс по RecId.
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
15.12.2010, 14:00 | #12 |
Участник
|
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:03 | #13 |
Ищущий знания...
|
на Ах 3.0 поле dataAreaId тоже не вычищается.
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
15.12.2010, 14:13 | #14 |
Administrator
|
Цитата:
А... сорри, не так понял. Я то думал - что не хватает курсору после null-а. И решил что dataareaid. А речь шла про то, что clear() не позволяет делать reread(). Хотя... у меня вариант от lev отработал также (т.е. запись все равно выбралась). Проверял на другом RecId (исключил вариант кеша)
__________________
Возможно сделать все. Вопрос времени |
|
15.12.2010, 14:18 | #15 |
Administrator
|
Кстати и на DAX2009 RU5 также отработало как и на 4.0 SP2
__________________
Возможно сделать все. Вопрос времени |
|
15.12.2010, 14:29 | #16 |
Участник
|
Странно, правда я проверял на AX2009SP1 без ролапов. Может ли ещё кто-нибудь проверить?
К стати, "InventTable = NULL" так же как и clear() сбрасывет dataAreaId к значению текущей компании X++: static void JobTestClearDataAreaId_2(Args _args) { InventTable InventTable; ; InventTable.(fieldnum(InventTable, dataAreaId)) = "XXX"; InventTable = NULL; info(InventTable.dataAreaId); } |
|
15.12.2010, 15:03 | #17 |
Administrator
|
Кажется понял - почему у меня сработало. В моем примере не было предыдущего reread(). Т.е. если в Вашем примере убрать первые строки с 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); }
__________________
Возможно сделать все. Вопрос времени |
|
|
За это сообщение автора поблагодарили: S.Kuskov (1). |
15.12.2010, 15:46 | #18 |
Участник
|
Действительно, clear не "портит" пустой курсор. Интересно, а есть ли вообще смысл в использовании метода clear(), ведь вместо него всегда можно присвоить курсору NULL? И как выясняется иногда это даже надёжнее
P.S.: Ещё проблемы с методом clear() - оригинальный orig: Последний раз редактировалось S.Kuskov; 15.12.2010 в 15:55. |
|
15.12.2010, 16:58 | #19 |
Administrator
|
Цитата:
Передаем курсор в какой-либо метод, который его (до)заполняет и вставляет / обновляет запись в БД. Передаем мы (к примеру) CustTrans. На "входе" в метод стоит параметр типа CustVendTrans или Common. Если в методе выполнить метод clear(), то он обнулит все поля, не изменив инициализацию входящего параметра. Т.е. наша переменная типа CustVendTrans (Common) будет все равно знать, что она на самом деле CustTrans-овая. Если же мы присвоим null, то наша переменная потеряет свою "CustTrans-овость". Что недопустимо, т.к. внутри метода - эта информация будет уже невосстановима.
__________________
Возможно сделать все. Вопрос времени |
|
|
За это сообщение автора поблагодарили: gl00mie (2), S.Kuskov (1). |