06.04.2010, 23:05 | #1 |
Участник
|
Kashperuk Ivan: Tutorial: refresh, reread, research, executeQuery - which one to use?
Источник: http://kashperuk.blogspot.com/2010/0...-research.html
============== X++ developers seem to be having a lot of trouble with these 4 datasource methods, no matter how senior they are in AX. So I decided to make a small hands-on tutorial, demonstrating the common usage scenario for each of the methods. I have ordered the methods based on the impact on the rows being displayed in the grid. You can download the xpo with the tutorial on my SkyDrive. 1. Common mistakes Often, developers call 2 of the mentioned methods in the following order: formDataSource.refresh() formDataSource.research() or formDataSource.reread() formDataSource.research() or formDataSource.research() formDataSource.executeQuery() or formDataSource.research() formDataSource.refresh() / formDataSource.reread() All of these are wrong, or at least partially redundant. Hopefully, after reading the full post, there will be no questions as to why they are wrong. Leave a comment to this post if one of them is still unclear, and I will try to explain in more detail. 2. Refresh This method basically refreshes the data displayed in the form controls with whatever is stored in the form cache for that particular datasource record. Calling refresh() method will NOT reread the record from the database. So if changes happened to the record in another process, these will not be shown after executing refresh(). refreshEx Does a redraw of the grid rows, depending on the optional argment for specifying the number of the record to refresh (and this means the actual row number in the grid, which is less useful for AX devs). Special argument values include -1, which means that all records will be redrawn, and -2, which redraws all marked records and records with displayOptions. Default argument value is -2. This method should be used sparingly, in cases where multiple rows from the grid are updated, resulting in changes in their displayOptions, as an example. So you should avoid using it as a replacement for refresh(), since they actually have completely different implementations in the kernel. Also, note, that refreshEx() only redraws the grid, so the controls not in the grid might still contain outdated values. Refresh() updates everything, since this is its intention. 3. Reread Calling reread() will query the database and re-read the current record contents into the datasource form cache. This will not display the changes on the form until a redraw of the grid contents happens (for example, when you navigate away from the row or re-open the form). You should not use it to refresh the form data if you have through code added or removed records. For this, you would use a different method described below. How are these 2 methods commonly used? Usually, when you change some values in the current record through some code (for example, when the user clicks on a button), and update the database by calling update method on the table buffer, you would want to show the user the changes that happened. In this case, you would call reread() method to update the datasource form cache with the values from the database (this will not update the screen), and then call refresh() to actually redraw the grid and show the changes to the user. Clicking buttons with SaveRecord == Yes Each button has a property SaveRecord, which is by default set to Yes. Whenever you click a button, the changes you have done in the current record are saved to the database. So calling reread will not restore the original record values, as some expect. If that is the user expectation, you as a developer should set the property to No. 4. Research Calling research() will rerun the existing form query against the database, therefore updating the list with new/removed records as well as updating all existing rows. This will honor any existing filters and sorting on the form, that were set by the user. Research(true) The research method starting with AX 2009 accepts an optional boolean argument _retainPosition. If you call research(true), the cursor position in the grid will be preserved after the data has been refreshed. This is an extremely useful addition, which solves most of the problems with cursor positioning (findRecord method is the alternative, but this method is very slow). 5. ExecuteQuery Calling executeQuery() will also rerun the query and update/add/delete the rows in the grid. The difference in behavior from research is described below. ExecuteQuery should be used if you have modified the query in your code and need to refresh the form to display the data based on the updated query. formDataSource.queryRun().query() vs formDataSource.query() An important thing to mention here is that the form has 2 instances of the query object - one is the original datasource query (stored in formDataSource.query()), and the other is the currently used query with any user filters applied (stored in formDataSource.queryRun().query()). When the research method is called, a new instance of the queryRun is created, using the formDataSource.queryRun().query() as the basis. Therefore, if the user has set up some filters on the displayed data, those will be preserved. This is useful, for example, when multiple users work with a certain form, each user has his own filters set up for displaying only relevant data, and rows get inserted into the underlying table externally (for example, through AIF). Calling executeQuery, on the other hand, will use the original query as the basis, therefore removing any user filters. This is a distinction that everyone should understand when using research/executeQuery methods in order to prevent possible collisions with the user filters when updating the query. Источник: http://kashperuk.blogspot.com/2010/0...-research.html
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору. |
|
|
За это сообщение автора поблагодарили: alex55 (1). |
07.04.2010, 02:50 | #2 |
Участник
|
Ой, хорошо то как!
Иван, появись в этой ветке, дай тебе респектов добавить. И по-русски бы... |
|
07.04.2010, 10:54 | #3 |
Moderator
|
|
|
07.04.2010, 17:11 | #5 |
Участник
|
Цитата:
Cтранно |
|
07.04.2010, 17:24 | #6 |
Участник
|
Цитата:
К примеру (я это вроде не включил в пример), создайте в примере доп.закладку, куда выведите те же поля, что и в гриде. Если обновить запись, находясь при этом на закладке без грида, то RefreshEx() не обновит поля, а Refresh() обновит, чего врядли бы случилось, если бы один вызывал другой. Там еще много муток с тем, где код выполняется, почему-то markRecord и getFirst()/getNext() возвращают разные результаты когда код выполняется на сервере/клиенте... но я баги посоздавал им, может пофиксят.. |
|
12.04.2010, 11:29 | #7 |
Участник
|
Альтернативным способом изменить данные текущей записи с обновлением на форме, может быть использование табличного курсора формы для модификации полей и запись новых значений в базу с помощью _ds.write()
|
|
14.05.2010, 16:18 | #8 |
Участник
|
Коллеги, есть DAX 2009 SP1 EE RU4.
При вызове research(true) данные обновляются, но сохраняется именно позиция грида (номер строки), а не конкретная запись - так и предполагалось? При добавлении / удалении строк грида номер исходной строки меняется и отображается уже совсем другая строка В исходной статье написано двояко: "the cursor position in the grid will be preserved" - т.е. сохранится позиция курсора на гриде, с другой стороны - "findRecord method is the alternative" - т.е. это якобы аналог полноценного поиска записи.
__________________
Ivanhoe as is.. |
|
14.05.2010, 20:45 | #9 |
Участник
|
research(true) потому так намного быстрее и работает, что работает напрямую с гридом (по сравнению с findRecord).
|
|
02.06.2011, 11:15 | #10 |
Участник
|
Цитата:
Более того воспроизвелся один неприятный глюк (живет еще с 3-ки) Пример. 1. Пользователь отфильтровал форму заказов по чекбоксу в гриде. 2. Жмет кнопку которая делает некую обработку с заказом, в результате которой галка снимается, таким образом заказ перестает попадать в выборку. 3. После обработки автоматом вызывается salesTable_ds.research(true); (раньше было salesTable_ds.research(); salesTable_ds.findRecord(common_Before) При исполнении ядро безуспешно пытается найти запись, затягивая все выборку заказов на клиент, сжирая всю оперативку на терминальном сервере. 70 тысяч заказов съели порядка 1 гига памяти. Судя по поведению аксапты salesTable_ds.research(true); внутри себя все таки дергает findRecord или аналогичный код. Проблему удалось решить только за счет использования X++: element.args().lookupField(fieldNum(SalesTable, salesID));
element.args().lookupValue(locSalesId); Можно еще было обязательно ограничивать выборку заказов с тем чтобы даже при таком глюке с базы не затягивалась большая выборка. Но это дело вкуса - кому что удобнее. P.S. Глюк в ядре немного странно себя ведет. Так как если в моем примере галка не снимается а ставится, то затягивания все выборки заказов в память не происходит. Почему - пока не разобрался. Возможно дело в сортировках. Последний раз редактировалось Logger; 02.06.2011 в 11:26. Причина: исправил опечатки в примерах кода |
|
|
За это сообщение автора поблагодарили: Ace of Database (3). |
29.03.2017, 12:38 | #11 |
Участник
|
X++: formDataSource.reread() formDataSource.research() В ситуации X++: for(tmp = custTrans_DS.getFirst(1) ? custTrans_DS.getFirst(1) : custTrans; tmp; tmp = custTrans_DS.getNext() ) { tmp.selectForUpdate(true); tmp.reread(); tmp.Amount = 100; tmp.update(); } custTrans_DS.reread(); custTrans_DS.research(); |
|
29.03.2017, 12:54 | #12 |
Участник
|
То есть вот так не срабатывает?
X++: for (tmp = custTrans_DS.getFirst(1) ? custTrans_DS.getFirst(1) : custTrans;
tmp; tmp = custTrans_DS.getNext() )
{
tmp.Amount = 100;
tmp.update();
}
custTrans_DS.research(); |
|
29.03.2017, 12:54 | #13 |
Участник
|
Какая версия системы?
|
|
29.03.2017, 14:58 | #14 |
Участник
|
А может это из-за того что какое-то значение в текущей строке под курсором было изменено пользователем ещё до выполнения обновлений в цикле, но не было сохранено в БД. Т.е. строка источника данных перешла в состояния редактирования. Тогда описываемое вами поведение объясняется тем, что research вызывает потерю фокуса на текущей строке, что в свою очередь вызывает сохранение ранее изменённых но ещё не сохранённых и уже не актуальных данных.
Хотя при такой последовательности действии наверное должна возникнуть ошибка вроде "Данные уже были изменены другим пользователем ..." или что-то в таком духе |
|
04.04.2017, 06:50 | #15 |
Участник
|
Цитата:
Версия dax4 ). На самом деле обновляются строки журнала цен скидок. Но код там такой же простой как в примере. |
|
04.04.2017, 07:06 | #16 |
Участник
|
Цитата:
Сообщение от S.Kuskov
А может это из-за того что какое-то значение в текущей строке под курсором было изменено пользователем ещё до выполнения обновлений в цикле, но не было сохранено в БД. Т.е. строка источника данных перешла в состояния редактирования. Тогда описываемое вами поведение объясняется тем, что research вызывает потерю фокуса на текущей строке, что в свою очередь вызывает сохранение ранее изменённых но ещё не сохранённых и уже не актуальных данных.
Хотя при такой последовательности действии наверное должна возникнуть ошибка вроде "Данные уже были изменены другим пользователем ..." или что-то в таком духе Проблемы нет если выделенных строк не много или выделили их не через "ctrl + A", а по честному все - т.е. shift+мышь, ctrl+мышь или встать на первую запись потом нажать shift+ctrl+end. Т.е. когда все изменяемые записи попали в кэш до запуска перебора. Получается когда подгружается кэш, текущий курсор помечается как обновленный. Вот стэк вызовов где происходит write текущего курсора [c] \Forms\PriceDiscAdm\Data Sources\PriceDiscAdmTrans\Methods\write 3 [c] \Classes\FormDataSource\leaveRecord [c] \Classes\FormDataSource\executeQuery [c] \Classes\FormDataSource\research [c] \Classes\FormButtonControl\Clicked 51 [c] \Classes\FormMenuButtonControl\Clicked |
|
04.04.2017, 07:55 | #17 |
Участник
|
А попробуйте в getFirst передать вторым параметром true
https://msdn.microsoft.com/en-us/lib...(v=ax.10).aspx Цитата:
fetchAhead
A Boolean with a default value of true. If false, only cached records are returned. If true, additional records are found and added to the cache. |
|
04.04.2017, 09:36 | #18 |
Участник
|
Цитата:
Сообщение от S.Kuskov
А попробуйте в getFirst передать вторым параметром true
https://msdn.microsoft.com/en-us/lib...(v=ax.10).aspx |
|
04.04.2017, 10:22 | #19 |
Участник
|
Цитата:
Так как getFirst() возвращает записи датасорса, они уже выбраны для редактирования по-умолчанию обычно. Либо же какой-то баг в 4ке. |
|
04.04.2017, 12:54 | #20 |
Участник
|
Да, пожалуй баг. Было ограничение на датасорсе приджойненом через 1:1. Проверил в этом ли причина. сделал новую простую форму с гридом и только лишь этой таблицей - нет, без селекта на обновление не обновляет).
|
|
Теги |
executequery, query, research, как правильно |
|
|