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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 15.04.2011, 16:20   #1  
Geo is offline
Geo
Участник
Аватар для Geo
 
258 / 47 (2) +++
Регистрация: 04.04.2008
Преобразование datasource и query в табличный курсор
Приветствую!

Есть метод, который обрабатывает набор данных из таблицы. Сейчас сделано так, что набор данных передается в метод параметром - табличным курсором, в виде
X++:
public static boolean SetCheckStorno(CustPackingSlipTrans _trans)
{
    // Обработка...
}

Потребовалось запускать этот метод для обработки записей, выводящихся на гриде, то есть с учетом установленных фильтров.

Вопрос: можно ли как-то преобразовать query датасорса в табличный курсор?
Если нет, то как посоветуете решать такую задачу - обработку данных с грида в независимом от грида методе?
Старый 15.04.2011, 16:29   #2  
kornix is offline
kornix
MCP
MCBMSS
Злыдни
Ex AND Project
 
414 / 146 (5) +++++
Регистрация: 24.02.2009
Адрес: Санкт-Петербург
Можно пробежаться QueryRun по Query датасорса формы и вызывать в цикле этот метод, т.е. если источник данных под гридом на форме называется CustPackingSlipTrans то метод будет выглядеть так:
X++:
void calc()
{
    Query                 query;
    QueryRun              qr;
    CustPackingSlipTrans  custPackingSlipTransLocal; 
    ;

    query = CustPackingSlipTrans_DS.query(); // query вашего датасорса
    qr    = new QueryRun(query);

    while (qr.next())
    {
         custPackingSlipTransLocal = qr.get(tableNum(custPackingSlipTrans)); // курсор с записью из грида
         element.SetCheckStorno(custPackingSlipTransLocal ); // вызов вашего метода
    }

}

Последний раз редактировалось kornix; 15.04.2011 в 16:35.
Старый 15.04.2011, 17:11   #3  
Geo is offline
Geo
Участник
Аватар для Geo
 
258 / 47 (2) +++
Регистрация: 04.04.2008
Спасибо за совет, но метод обрабатывает записи в зависимости друг от друга, то есть должен получать их сразу пакетом... Хм, может, мне описанным образом пробегаться по записям, в нужных случаях (а я их знаю) делать нужный Select и передавать его в метод?

Как скажется на быстродействии, если вместо одного большого Select'а делать много маленьких?
Старый 15.04.2011, 17:15   #4  
kornix is offline
kornix
MCP
MCBMSS
Злыдни
Ex AND Project
 
414 / 146 (5) +++++
Регистрация: 24.02.2009
Адрес: Санкт-Петербург
Цитата:
в нужных случаях (а я их знаю) делать нужный Select и передавать его в метод?
Так ведь в цикле вы и получите все записи по очереди, не совсем понял что значит "все записи сразу"?

Цитата:
Как скажется на быстродействии, если вместо одного большого Select'а делать много маленьких?
Лучше стараться избегать такие варианты
Старый 15.04.2011, 17:24   #5  
Geo is offline
Geo
Участник
Аватар для Geo
 
258 / 47 (2) +++
Регистрация: 04.04.2008
Цитата:
Сообщение от kornix Посмотреть сообщение
Так ведь в цикле вы и получите все записи по очереди, не совсем понял что значит "все записи сразу"?
Метод сам бегает по записям полученного табличного курсора и "в зависимости от" может их изменять или выдавать сообщения. На практике, пытается сопоставить между собой сторнированный записи. То есть запускать его на одной записи бессмысленно.

Может быть, идеологически правильно было бы переделать метод, чтобы он принимал QueryRun, а не табличный курсор, и работал уже с ним?
Старый 15.04.2011, 17:25   #6  
pitersky is offline
pitersky
северный Будда
Аватар для pitersky
Ex AND Project
Соотечественники
 
1,510 / 435 (18) +++++++
Регистрация: 26.09.2007
Адрес: Солнечная система
Тут уже много раз об этом писалось
Вот из последних - DataSource на форме, 4-е по порядку сообщение
__________________
С уважением,
Вячеслав

Последний раз редактировалось pitersky; 15.04.2011 в 17:32.
Старый 15.04.2011, 17:32   #7  
kornix is offline
kornix
MCP
MCBMSS
Злыдни
Ex AND Project
 
414 / 146 (5) +++++
Регистрация: 24.02.2009
Адрес: Санкт-Петербург
Цитата:
Сообщение от Geo Посмотреть сообщение
Может быть, идеологически правильно было бы переделать метод, чтобы он принимал QueryRun, а не табличный курсор, и работал уже с ним?
Если метод такой хитрый - возможно проще его переделать. По работе с датасорсами есть хорошая ветка. Что передавать на вход этому методу - вам видней, но если он работает с курсором и как-то перебирает в нем записи, наверно удобнее передать ему что-то другое
Старый 15.04.2011, 18:19   #8  
Geo is offline
Geo
Участник
Аватар для Geo
 
258 / 47 (2) +++
Регистрация: 04.04.2008
Спасибо за ответы!

Я думал, что QeuryRun это по сути и есть табличная переменная - а вот поди ж ты, никак не вытащить в явном виде, только по одной записи...

Цитата:
Сообщение от pitersky Посмотреть сообщение
Тут уже много раз об этом писалось
Вот из последних - DataSource на форме, 4-е по порядку сообщение
Это не то. Я хотел не пробежаться по записям, а сформировать одну табличную переменную, а-ля вызов "Select xTable Where ...", и потом хTable передать в метод, чтобы он с ней работал.

Я пробовал Table1_ds.cursor() - он возвращает одну запись. Пробовал целиком Table1 - возвращается вся таблица, без фильтров.


Цитата:
Сообщение от kornix Посмотреть сообщение
Если метод такой хитрый - возможно проще его переделать. По работе с датасорсами есть хорошая ветка. Что передавать на вход этому методу - вам видней, но если он работает с курсором и как-то перебирает в нем записи, наверно удобнее передать ему что-то другое
Читал, но там тоже речь о переборе записей.
Что ж, наверное, так и буду делать: не пытаться передать табличную переменную в метод, а передавать QueryRun, или иным способом из метода получать доступ к DS или QueryRun, как описано в тех ветках.

Жаль; мне казалось, что табличная переменная - это удобно.
Старый 15.04.2011, 18:26   #9  
pitersky is offline
pitersky
северный Будда
Аватар для pitersky
Ex AND Project
Соотечественники
 
1,510 / 435 (18) +++++++
Регистрация: 26.09.2007
Адрес: Солнечная система
Geo, таблица тут вообще ни при чём. Выделенность - свойство датасоурса.
__________________
С уважением,
Вячеслав
Старый 15.04.2011, 18:37   #10  
Geo is offline
Geo
Участник
Аватар для Geo
 
258 / 47 (2) +++
Регистрация: 04.04.2008
Так мне выделенность и не нужна, мне фильтры нужны. А целиком Table1 я пробовал на всякий случай.
Думал, есть что-нибудь вроде table_ds.tableVariable() или queryRun.tableVariable()
Старый 18.04.2011, 14:08   #11  
kornix is offline
kornix
MCP
MCBMSS
Злыдни
Ex AND Project
 
414 / 146 (5) +++++
Регистрация: 24.02.2009
Адрес: Санкт-Петербург
Честно говоря я никак не могу сообразить: что нужно получить в итоге?
Но если нужен фильтр - это однозначно Query датасорса. Если вам нужен фильтр и метод обрабатывает данные каким-то хитрым способом, в зависимости от наложенного фильтра - можно использовать в качестве параметра query.

P.S.: QueryRun в качестве входного параметра использовать не желательно, т.к. обычно приходится добавлять условия в Query и получится такая картина: где-то был сформирован query, вы где-то от него сделали queryRun, потом передали его в метод, в методе опять получили от него query дополнили условия и т.п.

Последний раз редактировалось kornix; 18.04.2011 в 14:11.
Старый 18.04.2011, 14:21   #12  
CDR is offline
CDR
MCTS
MCBMSS
 
236 / 175 (6) ++++++
Регистрация: 27.11.2003
Цитата:
Сообщение от Geo Посмотреть сообщение
Потребовалось запускать этот метод для обработки записей, выводящихся на гриде, то есть с учетом установленных фильтров.
Цитата:
Сообщение от Geo Посмотреть сообщение
Так мне выделенность и не нужна, мне фильтры нужны.
Обрабатывать записи, выводящиеся в грид - не совсем правильно, т.к. в общем случае пользователь может и не видеть ВСЕХ отфильтрованных записей, которые выводятся в грид. Более того, аксапта может и не выбрать из БД все отфильтрованные записи для отображения на форме (например, условиям фильтра удовлетворяют 100 записей, на форме отображаются 15 записей, а в курсор из базы выбраны только 30 записей).

Обрабатывать стоит именно явно выделенные (промаркированные) пользователем записи, и каждую запись передавать в метод.
__________________
Dynamics AX Experience
Старый 18.04.2011, 15:16   #13  
_scorp_ is offline
_scorp_
Участник
Аватар для _scorp_
MCBMSS
 
488 / 369 (13) ++++++
Регистрация: 25.07.2007
Адрес: Москва
Цитата:
Сообщение от Geo Посмотреть сообщение
Жаль; мне казалось, что табличная переменная - это удобно.
Похоже Вы пришли из 1С. Там очень любят пользоваться "ТаблицамиЗначений". В AX другой подход.
Если Вы пытаетесь сопоставить какие-то проводки, сделайте на форме кнопку, которая будет вызывать класс, выполняющийся на сервере. В этом классе вызывайте свой метод и передавайте в него просто критерии сопоставления (полученные из Args). Например, по такому-то то клиенту, за такой-то период. Накапливать данные во временных таблицах и "бегать" по ним - это крайний случай. Обычно достаточно выбора записей для обновления в определенном порядке (с заданным order by). После отработки класса обновите данные на форме.
Старый 18.04.2011, 19:25   #14  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
тоже не очень понимаю что нужно.
Geo, может сформулируете на человеческом языке исходную задачу?
Цитата:
Сообщение от Geo Посмотреть сообщение
Я думал, что QeuryRun это по сути и есть табличная переменная
Query - запрос
QueryRun - результаты, которые SQL-сервер отдает в ответ на Query
QueryRun - позволяет обратится к текущей полученной позиции (одна запись, если таблица одна, или по одной записи на каждую таблицу в запросе).
QueryRun.get() - метод, который возвращает данные в табличную переменную
табличная переменная - хранит данные из одной записи таблицы
внимание! если табличная переменная получена в результате select, то к ней можно применить next.

типичный пример работы с query
X++:
void job1(Args args)
{
    MyTable myTable;
    Query q = new Query(queryStr(myAOTQuery); // внутри что-то вроде select * from myTable;
    QueryRun qr = new QueryRun(q);

    while( qr.next() ) // в первый проход запрос отправляется на SQL-сервер
    {
        myTable = qr.get(myTable.TableId);
        ///....
    }
}
в форме:
myTable_ds.query() - запрос, который создал программист в AOT
myTable_ds.queryRun() - результаты, которые выводятся в форму. Будьте внимательны с позиционированием и next.
myTable_ds.queryRun().Query() - запрос, который действует в данный момент для данного экземпляра формы. Может отличаться от первоначального, если пользователь задаст фильтры, сортировку и т.п.

Цитата:
Сообщение от Geo Посмотреть сообщение
- а вот поди ж ты, никак не вытащить в явном виде, только по одной записи...
Что именно?

Цитата:
Сообщение от Geo Посмотреть сообщение
Это не то. Я хотел не пробежаться по записям, а сформировать одну табличную переменную, а-ля вызов "Select xTable Where ...", и потом хTable передать в метод, чтобы он с ней работал.
Что вы называете табличной переменной?
в следующем выражении
LedgerTrans ltr;

переменная ltr является табличной в вашем понимании?

надо отметить, что в Аксапте query и select-написанный-в-коде никогда не пересекаются. и никогда друг в друга не преобразуются. это два совершенно разных инструмента. Query никогда не преобразуется в select, а select никогда не преобразуется в Query.


Цитата:
Сообщение от Geo Посмотреть сообщение
Жаль; мне казалось, что табличная переменная - это удобно.
нет. это сильно устаревший и унаследованный от старых версий механизм, от которого никак не могут отказаться.

в "табличных переменных" и в select'ах не работают пользовательские фильтры с запятыми, восклицательными знаками и прочими символами.
кроме того, select нельзя динамически модифицировать.


Цитата:
Сообщение от Geo Посмотреть сообщение
Так мне выделенность и не нужна, мне фильтры нужны.
фильтры из Query не работают в select.
__________________
полезное на axForum, github, vk, coub.
За это сообщение автора поблагодарили: Geo (1).
Старый 18.04.2011, 19:48   #15  
lvan is offline
lvan
Участник
Аватар для lvan
Лучший по профессии 2014
 
858 / 82 (4) ++++
Регистрация: 15.04.2011
Записей в блоге: 1
Что-то вы не правильное делаете
Используйте формы (и, соответственно, датасорты) для отображения данных
Для обработки используйте классы

Если в качестве входных параметров вам нужны данные, которые выбираются на форме, то можно использовать временную таблицу для их передачи (как например на форме InventTransRegister) Обратите внимание на то, что она инициализируется на сервере.

Ваше решение с queryRun неверно с точки зрения бест практисес, так как экземпляр queryRun скорее всего будет на клиенте и будет генерить запросы к серверу. В итоге это может привести к тормозам
За это сообщение автора поблагодарили: Geo (0).
Старый 19.04.2011, 00:13   #16  
Geo is offline
Geo
Участник
Аватар для Geo
 
258 / 47 (2) +++
Регистрация: 04.04.2008
Большое спасибо за советы.

По постановке задачи, мне нужно из формы Отборочных накладных продажи запускать обработку, которая постарается за (какое-то) последнее время автоматически проставить признак сторно в сторнированную/сторнирующую строки накладных (добавлен такой нами) и выдаст предупреждения в тех случаях, когда сделать этого (автоматически) не сможет.

Желание использовать фильтр грида (обрабатывать только те строки Отборочных, которые ему удовлетворяют) вызвано тем, что за Отборочные отвечают разные люди. Сооответственно, пользователю не нужно видеть предупреждения по "не его" Отборочным, да и проставлять сторно по "чужим" не следовало бы, наверное. Поэтому мне не хватило бы только критерия даты. Еще могут потребоваться, как минимум, номенклатура и код создавшего запись пользователя; а вообще там можно предположить разные фильтры. Потому я и хочу брать в обработку только те записи, которые пользователь сам для себя отфильтровал для работы, с произвольными критериями.


Цитата:
Сообщение от mazzy Посмотреть сообщение
тоже не очень понимаю что нужно.
QueryRun - результаты, которые SQL-сервер отдает в ответ на Query
Вот это я изначально и хотел получить - результаты, которые SQL-сервер отдает в ответ на Query. Не по одной записи (как делает QueryRun.get()), а сразу всё, чтобы передать в метод и там обработать. Вижу по обсуждению, что такого в АХ не предусмотрено.


Цитата:
Что вы называете табличной переменной?
в следующем выражении
LedgerTrans ltr;

переменная ltr является табличной в вашем понимании?
С терминологией я пока не до конца определился, но да: в моем понимании ltr является табличной переменной. А если сделать потом
Select ltr Where ltr.transDate == xx\xx\xxxх;
, то уж точно.


Цитата:
надо отметить, что в Аксапте query и select-написанный-в-коде никогда не пересекаются. и никогда друг в друга не преобразуются. это два совершенно разных инструмента. Query никогда не преобразуется в select, а select никогда не преобразуется в Query.
Собственно, ровно это я и хотел узнать в первом посте темы. Спасибо
Обозвал только табличную переменную табличным курсором (думал, что это синонимы )
Старый 19.04.2011, 00:18   #17  
Geo is offline
Geo
Участник
Аватар для Geo
 
258 / 47 (2) +++
Регистрация: 04.04.2008
Цитата:
Сообщение от CDR Посмотреть сообщение
Обрабатывать записи, выводящиеся в грид - не совсем правильно, т.к. в общем случае пользователь может и не видеть ВСЕХ отфильтрованных записей, которые выводятся в грид. Более того, аксапта может и не выбрать из БД все отфильтрованные записи для отображения на форме (например, условиям фильтра удовлетворяют 100 записей, на форме отображаются 15 записей, а в курсор из базы выбраны только 30 записей).

Обрабатывать стоит именно явно выделенные (промаркированные) пользователем записи, и каждую запись передавать в метод.
Хм, но разве так делают в большинстве случаев, обрабатывают только явно выделенные записи? Мне казалось, в описываемых на форуме задачах как правило обращались к гриду, не рассматривая маркировку...
Старый 19.04.2011, 00:41   #18  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Geo Посмотреть сообщение
Вот это я изначально и хотел получить - результаты, которые SQL-сервер отдает в ответ на Query. Не по одной записи (как делает QueryRun.get()), а сразу всё, чтобы передать в метод и там обработать. Вижу по обсуждению, что такого в АХ не предусмотрено.
Как это не предусмотрено?! *впал в ступор*

queryRun - это и есть результаты, которые SQL-сервер отдает в ответ на Query.
__________________
полезное на axForum, github, vk, coub.
Старый 19.04.2011, 01:01   #19  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Geo Посмотреть сообщение
Мне казалось, в описываемых на форуме задачах как правило обращались к гриду, не рассматривая маркировку...
нет. не надо обращаться "к гриду".
грид живет на клиенте. данные живут на сервере.
со всеми вытекающими последствиями для трафика и производительности
вам уже об этом говорили.

===============
по поводу "выделенных строк" см axaptapedia: Tutorial Form MultiSelectCheckBox
но обратите внимание, что "выделенные строки" и "отфильтрованные строки" - разные вещи.
__________________
полезное на axForum, github, vk, coub.
Старый 19.04.2011, 10:09   #20  
pitersky is offline
pitersky
северный Будда
Аватар для pitersky
Ex AND Project
Соотечественники
 
1,510 / 435 (18) +++++++
Регистрация: 26.09.2007
Адрес: Солнечная система
Цитата:
Сообщение от mazzy Посмотреть сообщение
нет. не надо обращаться "к гриду".
грид живет на клиенте. данные живут на сервере
...
но обратите внимание, что "выделенные строки" и "отфильтрованные строки" - разные вещи.
Именно поэтому в общем случае не обойтись без клиент-серверного трафика. Одно дело, когда мы запускаем обработку по записям с объективным уровнем общности (одинаковые значения полей, на которые можно наложить фильтр), и совсем другое - если пользователь хочет обработать произвольный набор записей, ничем не объединённый (кроме его доброй воли).

И кстати говоря - не стал бы я так уж хаять механизм селектов. Достаточно много есть задач, где нужна жёсткая выборка с простейшим суммированием, типа
X++:
while select sum(Qty)
from MyTable
group by ItemId
{...}
Разворачивать здесь Query ИМХО = стрелять из пушки по воробьям. Т.е. можно, но зачем?
__________________
С уважением,
Вячеслав

Последний раз редактировалось pitersky; 19.04.2011 в 10:14.
Теги
grid, query, датасорс (datasource), табличный курсор, фильтр

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
jinx: Dynamics AX – Query-Ranges und Filtereinstellungen des Benutzers Blog bot DAX auf Deutsch 0 04.02.2010 00:05
Query на Datasource в LookUp-форме. dynamax DAX: Программирование 26 09.10.2009 15:58
Как удалить DataSource из Query??? Maxim Gorbunov DAX: Программирование 17 01.09.2008 14:00
axcoder: Tabax 0.2.14: View query of the active datasource Blog bot DAX Blogs 2 02.02.2007 12:10
How do I delete a datasource from a query ? (by stelsig) Maxim Gorbunov DAX in English 0 22.03.2006 12:21

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

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

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 21:14.