AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX Blogs
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 06.04.2010, 23:05   #1  
Blog bot is offline
Blog bot
Участник
 
25,607 / 848 (80) +++++++
Регистрация: 28.10.2006
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  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Ой, хорошо то как!
Иван, появись в этой ветке, дай тебе респектов добавить.

И по-русски бы...
__________________
полезное на axForum, github, vk, coub.
Старый 07.04.2010, 10:54   #3  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от mazzy Посмотреть сообщение
И по-русски бы...
По-русски нам уже как-то написал "китайский стажер"

Research, refresh, reread шпаргалка
Старый 07.04.2010, 11:42   #4  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
Хмм, да, по сути "китайский стажер" сказал приблизительно то же самое, может чуть более кратко, и по-русски
За это сообщение автора поблагодарили: mazzy (5), raz (7), zemlyn (1), Logger (8), Silphidae (1).
Старый 07.04.2010, 17:11   #5  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,932 / 3227 (115) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от Blog bot Посмотреть сообщение
So you should avoid using it as a replacement for refresh(), since they actually have completely different implementations in the kernel.
хм. Мне казалось что я видел стеки вызовов где из refresh() вызывался refreshEx() из чего я сделал вывод что refresh() - это частный случай refreshEx()

Cтранно
Старый 07.04.2010, 17:24   #6  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
Цитата:
Сообщение от Logger Посмотреть сообщение
хм. Мне казалось что я видел стеки вызовов где из refresh() вызывался refreshEx() из чего я сделал вывод что refresh() - это частный случай refreshEx()

Cтранно
Да, я тоже так думал до недавнего времени. Но они на самом деле ведут себя совсем по разному.

К примеру (я это вроде не включил в пример), создайте в примере доп.закладку, куда выведите те же поля, что и в гриде.
Если обновить запись, находясь при этом на закладке без грида, то RefreshEx() не обновит поля, а Refresh() обновит, чего врядли бы случилось, если бы один вызывал другой.

Там еще много муток с тем, где код выполняется, почему-то
markRecord и getFirst()/getNext() возвращают разные результаты когда код выполняется на сервере/клиенте... но я баги посоздавал им, может пофиксят..
Старый 12.04.2010, 11:29   #7  
Irv is offline
Irv
Участник
 
8 / 11 (1) +
Регистрация: 18.05.2006
Альтернативным способом изменить данные текущей записи с обновлением на форме, может быть использование табличного курсора формы для модификации полей и запись новых значений в базу с помощью _ds.write()
Старый 14.05.2010, 16:18   #8  
Ivanhoe is offline
Ivanhoe
Участник
Аватар для Ivanhoe
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
4,143 / 2156 (80) +++++++++
Регистрация: 29.09.2005
Адрес: Санкт-Петербург
Коллеги, есть 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  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
research(true) потому так намного быстрее и работает, что работает напрямую с гридом (по сравнению с findRecord).
Старый 02.06.2011, 11:15   #10  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,932 / 3227 (115) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от kashperuk Посмотреть сообщение
research(true) потому так намного быстрее и работает, что работает напрямую с гридом (по сравнению с findRecord).
В 2009-й не заметил особой разницы.
Более того воспроизвелся один неприятный глюк (живет еще с 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  
Perc is offline
Perc
Участник
 
194 / 57 (2) ++++
Регистрация: 05.03.2005
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();
и большом количестве выделенных записей (через ctrl + A) в форме мне помог только reread. Видимо когда getNext начинает грузить в кэш, текущий курсор вдруг решает что ему надо сохраниться и research сначала сохраняет устаревший буфер. А потом честно загружает все с БД.
Старый 29.03.2017, 12:54   #12  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
То есть вот так не срабатывает?

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  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
Какая версия системы?
Старый 29.03.2017, 14:58   #14  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,435 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Perc Посмотреть сообщение
research сначала сохраняет устаревший буфер
А может это из-за того что какое-то значение в текущей строке под курсором было изменено пользователем ещё до выполнения обновлений в цикле, но не было сохранено в БД. Т.е. строка источника данных перешла в состояния редактирования. Тогда описываемое вами поведение объясняется тем, что research вызывает потерю фокуса на текущей строке, что в свою очередь вызывает сохранение ранее изменённых но ещё не сохранённых и уже не актуальных данных.

Хотя при такой последовательности действии наверное должна возникнуть ошибка вроде "Данные уже были изменены другим пользователем ..." или что-то в таком духе
Старый 04.04.2017, 06:50   #15  
Perc is offline
Perc
Участник
 
194 / 57 (2) ++++
Регистрация: 05.03.2005
Цитата:
Сообщение от kashperuk Посмотреть сообщение
То есть вот так не срабатывает?

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();
так не работает вообще - без selectForUpdate и reread не обновляется ни одна запись
Версия dax4 ).
На самом деле обновляются строки журнала цен скидок. Но код там такой же простой как в примере.
Старый 04.04.2017, 07:06   #16  
Perc is offline
Perc
Участник
 
194 / 57 (2) ++++
Регистрация: 05.03.2005
Цитата:
Сообщение от 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  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,435 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Perc Посмотреть сообщение
Т.е. когда все изменяемые записи попали в кэш до запуска перебора.
А попробуйте в 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  
Perc is offline
Perc
Участник
 
194 / 57 (2) ++++
Регистрация: 05.03.2005
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
А попробуйте в getFirst передать вторым параметром true
https://msdn.microsoft.com/en-us/lib...(v=ax.10).aspx
getFirst(1, true) работает так как и описано в документации. true по умолчанию, перебираются все выделенные записи; false - только те видимо, что были в кэше на момент нажатия ctrl+a. Спортивного интереса ради проверил быстро - в моем случае штук 30. Логично что при false проблема с обновлением текущей записи исчезает
Старый 04.04.2017, 10:22   #19  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
Цитата:
Сообщение от Perc Посмотреть сообщение
так не работает вообще - без selectForUpdate и reread не обновляется ни одна запись
Версия dax4 ).
На самом деле обновляются строки журнала цен скидок. Но код там такой же простой как в примере.
Видимо записи на форму выбираются либо с группировкой либо с еще какими-то ограничениями (может allowEdit = false на датасорсе?).

Так как getFirst() возвращает записи датасорса, они уже выбраны для редактирования по-умолчанию обычно.

Либо же какой-то баг в 4ке.
Старый 04.04.2017, 12:54   #20  
Perc is offline
Perc
Участник
 
194 / 57 (2) ++++
Регистрация: 05.03.2005
Цитата:
Сообщение от kashperuk Посмотреть сообщение
Видимо записи на форму выбираются либо с группировкой либо с еще какими-то ограничениями (может allowEdit = false на датасорсе?).

Так как getFirst() возвращает записи датасорса, они уже выбраны для редактирования по-умолчанию обычно.

Либо же какой-то баг в 4ке.
Да, пожалуй баг. Было ограничение на датасорсе приджойненом через 1:1. Проверил в этом ли причина. сделал новую простую форму с гридом и только лишь этой таблицей - нет, без селекта на обновление не обновляет).
Теги
executequery, query, research, как правильно

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Research, refresh, reread шпаргалка Qaz Qwerty DAX: База знаний и проекты 7 03.05.2024 12:17
Kashperuk Ivan: Casing and text search/comparison tutorial Blog bot DAX Blogs 6 25.02.2010 15:41
Kashperuk Ivan: Lookup methods tutorial + custom list lookup implementation Blog bot DAX Blogs 0 04.05.2009 14:05
Kashperuk Ivan: TableBrowser.NET (a small .NET BC tutorial) Blog bot DAX Blogs 0 18.10.2008 02:08
Kashperuk Ivan: Dynamics AX Tutorials - Tutorial 2 - Classes\Box Blog bot DAX Blogs 0 25.04.2007 22:23

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 23:09.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.