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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 16.11.2010, 09:11   #1  
Blog bot is offline
Blog bot
Участник
 
25,643 / 848 (80) +++++++
Регистрация: 28.10.2006
Preston.Larimer: Dynamic selection criteria in X++
Источник: http://palarimer.greenlight2go.com/2...eria-in-x.html
==============


Occasionally I’ve had a situation where using a while select statement to loop through a set of records and needed the fields used in the selection criteria to be dynamic based on arguments passed to the method. Dynamics AX offers a slick way of dealing with this that is used in the standard application code but is still pretty obscure. The following method demonstrates using a variable select statement based on passed in arguments and using the NEXT keyword to move the record set forward. In this example we’re just outputting the Item ID to an info log but you could get much more creative….

X++:
void SelectNextSample(salesID _salesID, inventtransID _inventTransID = '')
{    
    salesLine salesLine;    
    ;        

    if (_inventTransID)    
    {        
        select salesLine where salesLine.SalesId == _salesID && salesLine.InventTransId == _inventTransID;    
    }
    else
    {        
        select salesLine where salesLine.SalesId == _salesID;    
    }

    while (salesLine)    
    {        
        info(salesLine.ItemId);
        next salesLine;    
    }
}


Источник: http://palarimer.greenlight2go.com/2...eria-in-x.html
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору.
Старый 16.11.2010, 09:40   #2  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,340 / 3558 (125) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Пример неудачный. В этом случае (с if) лучше Query воспользоваться. Но формально - такой код работать будет
__________________
Возможно сделать все. Вопрос времени
За это сообщение автора поблагодарили: mazzy (2).
Старый 16.11.2010, 09:40   #3  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
эээ, а почему не сделать проще? вот так например:
X++:
void SelectNextSample(salesID _salesID, inventtransID _inventTransID = '')
{    
    salesLine salesLine;    
    ;        

    while select salesLine 
             where salesLine.SalesId           == _salesID           && 
                      (salesLine.InventTransId ==  _inventTransID || _inventTransID == '')    
    {        
        info(salesLine.ItemId);
    }
}
и не нужны никакие IF-ы и NEXT-ы
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
Старый 16.11.2010, 09:45   #4  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,340 / 3558 (125) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
2lev: Я ж говорю - пример неудачный. Возможно, автор в своем примере хотел показать - что если саму выборку конструировать отдельно от цикла пробега - то есть оператор next. В случае с Query это бывает актуально - когда один метод конструирует запрос, а второй - бегает по циклу.

Эх... жаль, если такие люди пишут sys-слой АХ...
__________________
Возможно сделать все. Вопрос времени
Старый 16.11.2010, 09:49   #5  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,448 / 1789 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Вспомнил сейчас только один случай из своей практики, когда мне действительно понадобилось вручную управлять движением курсоров. Задача требовала независимого движения двух курсоров по одной выборке.
Старый 16.11.2010, 10:02   #6  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
Цитата:
Сообщение от sukhanchik Посмотреть сообщение
2lev: Я ж говорю - пример неудачный. Возможно, автор в своем примере хотел показать - что если саму выборку конструировать отдельно от цикла пробега - то есть оператор next. В случае с Query это бывает актуально - когда один метод конструирует запрос, а второй - бегает по циклу.
ааа, если имелось это ввиду, тогда конечно лучше Query использовать...

Цитата:
Сообщение от sukhanchik Посмотреть сообщение
Эх... жаль, если такие люди пишут sys-слой АХ...
Ага
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
Старый 16.11.2010, 10:36   #7  
oip is offline
oip
Axapta
Лучший по профессии 2014
 
2,564 / 1416 (53) ++++++++
Регистрация: 28.11.2005
Записей в блоге: 1
Цитата:
Сообщение от lev Посмотреть сообщение
эээ, а почему не сделать проще? вот так например:
Я понимаю, что salesLine.InventTransId по хорошему должен быть непустым, но правильнее сделать все-таки вот так:
X++:
void SelectNextSample(salesID _salesID, inventtransID _inventTransID = '')
{    
    salesLine salesLine;    
    ;        

    while select salesLine 
             where salesLine.SalesId           == _salesID           && 
                      // (salesLine.InventTransId ==  _inventTransID || _inventTransID == '')   
                      (_inventTransID == '' || salesLine.InventTransId ==  _inventTransID)    
    {        
        info(salesLine.ItemId);
    }
}
А пример у автора, конечно, ужасен.
За это сообщение автора поблагодарили: lev (1).
Старый 16.11.2010, 11:03   #8  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
Цитата:
Сообщение от oip Посмотреть сообщение
Я понимаю, что salesLine.InventTransId по хорошему должен быть непустым, но правильнее сделать все-таки вот так: ...
А пример у автора, конечно, ужасен.
с замечанием согласен.
когда писал пример не заострил внимание на логическом построении условия с inventTransId. Конечно лучше вначале проверить заполнена ли переменная с критерием, а потом уже проверить соответствие этой переменной с полем в таблице.
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
Старый 16.11.2010, 11:36   #9  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,448 / 1789 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от oip Посмотреть сообщение
но правильнее сделать все-таки вот так:
Вообще по хорошему вычисление выражения (_inventTransID == '') должно быть выполнено оптимизатором до цикла. И на SQL-сервер должен уйти следующий запрос, который в свою очередь должен быть в итоге соптимизирован до простейшего запроса.

Код:
select salesLine 
where 
    salesLine.SalesId           == _salesID           && 
    (salesLine.InventTransId ==  _inventTransID || true)
Код:
// Оптимизируем
select salesLine 
where 
    salesLine.SalesId == _salesID && true
Код:
// Ещё раз оптимизируем
select salesLine 
where 
    salesLine.SalesId == _salesID
Но это всё в теории. Происходят ли подобные оптимизации на самом деле? Было бы логично
Старый 16.11.2010, 11:44   #10  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от sukhanchik Посмотреть сообщение
Эх... жаль, если такие люди пишут sys-слой АХ...
Агась
__________________
полезное на axForum, github, vk, coub.
Старый 16.11.2010, 16:26   #11  
petr is offline
petr
Участник
Соотечественники
 
561 / 201 (8) ++++++
Регистрация: 30.05.2005
Адрес: Швейцария
Не понимаю наездов на исходный код, он на 100% правильно написан.

1). Если нет взаимодействия с пользователем или сбора query() в подклассах, лучше писать select, чем использовать query() - гораздо наглядней, особенно в отладчике.
2) Приведенная автором блога конструкция гораздно нагляднее всех предложенных альтернатив.
3) Проверка на непустое значение inventTransID присутствует, код корректен.

Еще никогда не видел у партнеров код лучше, чем от MS (если не брать некоторые модули, которые MS купил у партнеров), но видел много кода написанного партнерами и клиентами (компания FWI тут приятное исключение, но мы писали не лучше чем в стандарте, просто на уровне, ИМХО), который гораздно хуже кода MS. Поэтому не понимаю ехидства по отношению к автору.
Старый 16.11.2010, 16:35   #12  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
т.е. вы считаете нормальным написания 100 строк кода вместо 5-ти?
а если у программиста дрогнет рука и он забудет про next, тогда сколько мы будем ждать пока код выполниться?

когда код избыточен, он менее читаем, это факт.
когда код сильно зависим от человеческого фактора (не люблю next-ы) то же не есть гуд.

да конечно, код рабочий, но у него много но, ИМХО.
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
Старый 16.11.2010, 16:42   #13  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,448 / 1789 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от petr Посмотреть сообщение
Не понимаю наездов на исходный код, он на 100% правильно написан.
Если правильно написан означает компилируется и проходит тесты, то да. Этого здесь никто и не отрицал.

Критику не выдерживает сам подход использования статичестких select'ов против динамического построения Query.
Представьте себе, что помимо добавления условия по _inventTransID необходимо станет управлять ну скажем фильтром по InventDimId. Тогда один if разрастётся на 4 ветки:

учитываем inventTransID и не учитываем InventDimId
не учитываем inventTransID и учитываем InventDimId
учитываем inventTransID и учитываем InventDimId
не учитываем inventTransID и не учитываем InventDimId

А что делать если таких условий ещё больше? И вы действительно считаете что такой код сопровождать легче?
Старый 16.11.2010, 16:48   #14  
petr is offline
petr
Участник
Соотечественники
 
561 / 201 (8) ++++++
Регистрация: 30.05.2005
Адрес: Швейцария
Процитирую сам себя:
Цитата:
1). Если нет взаимодействия с пользователем или сбора query() в подклассах, лучше писать select, чем использовать query() - гораздо наглядней, особенно в отладчике.
Старый 16.11.2010, 16:51   #15  
petr is offline
petr
Участник
Соотечественники
 
561 / 201 (8) ++++++
Регистрация: 30.05.2005
Адрес: Швейцария
To S.Kuskov:

Можно и в методе find() использовать query(), вдруг кто-то через десять лет сделать уникальный ключ составным из 10 полей, тогда query() будет удобней.
Старый 16.11.2010, 16:53   #16  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
Цитата:
Сообщение от petr Посмотреть сообщение
Процитирую сам себя:
я бы сказал не наглядней, а привычней в отладчике видно как запрос строится и какие условия туда подставляются
+ в query более наглядно подставляется критерий в зависимости от его заполнености.

например, на мой взгляд, вот это:
X++:
if (_itemId != '')
    qbdsInventTable.addRange(fieldNum(InventTable, ItemId)).value(QueryValue(_itemId));
нисколько не уступает в наглядности (а то и превосходит) вот этому:
X++:
select inventTable
   where _itemId == '' || inventTable.ItemId == _itemId;
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
Старый 16.11.2010, 16:54   #17  
petr is offline
petr
Участник
Соотечественники
 
561 / 201 (8) ++++++
Регистрация: 30.05.2005
Адрес: Швейцария
To lev:

Там не 100 строк всето 5-ти. Если было бы так - тогда надо что-то придумывать (query или то, что вы предложили).

Но для изначально стоящей задачи (метод принимает 2 переменные) - предложенный код самый наглядный и возможно самый быстрый (принимая во внимание замечание S.Kuskov про оптимизатор).
Старый 16.11.2010, 16:57   #18  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
Цитата:
Сообщение от petr Посмотреть сообщение
To S.Kuskov:

Можно и в методе find() использовать query(), вдруг кто-то через десять лет сделать уникальный ключ составным из 10 полей, тогда query() будет удобней.
тут говорят про взвешенный подход к написанию кода, а не пропагандируют использования чего либо (в нашем случае query) везде где только возможно, доводя его использование до абсурда.
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
Старый 16.11.2010, 16:58   #19  
petr is offline
petr
Участник
Соотечественники
 
561 / 201 (8) ++++++
Регистрация: 30.05.2005
Адрес: Швейцария
Кроме того, уважаемые участники.

Если бы в этом методе был использован query() - ок
Если бы было написано так, как предложил lev - ок

Два эти подхода тоже хороши и часто используются, я против них ничего не имею.

Просто я считаю, что изначальный вариант не чем не хуже и не стоит на него набрасываться. Притом не понятно с какой стати ехидничать над авторами стандарта, притом что код там очень хорош.
Старый 16.11.2010, 17:00   #20  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
Цитата:
Сообщение от petr Посмотреть сообщение
To lev:

Там не 100 строк всето 5-ти. Если было бы так - тогда надо что-то придумывать (query или то, что вы предложили).

Но для изначально стоящей задачи (метод принимает 2 переменные) - предложенный код самый наглядный и возможно самый быстрый (принимая во внимание замечание S.Kuskov про оптимизатор).
про 100 строк я утрировал.
если возможно написать один запрос и в нем обработать нужные условия, зачем писать два запроса, и обрабатывать условия по IF? + написание цикла while становиться опасным, а не забудет ли программист про next?
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Preston.Larimer: Item import from CSV file made easy (Kinda) Blog bot DAX Blogs 3 15.11.2010 12:26
Preston.Larimer: Workflow setup error on Event Log name Blog bot DAX Blogs 0 14.11.2010 10:18
Microsoft Dynamics CRM Team Blog: Marketing with Dynamic List Blog bot Dynamics CRM: Blogs 0 09.11.2010 19:05
Microsoft Dynamics CRM Team Blog: Dynamic Export to Excel feature – How to protect data over the wire Blog bot Dynamics CRM: Blogs 0 27.01.2009 10:05

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

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

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