Показать сообщение отдельно
Старый 17.04.2007, 21:01   #2  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Blog bot Посмотреть сообщение
Такие операции существенно уменьшают число запросов к базе данных и позволяют улучшить производительность операций.
Такие операции МОГУТ уменьшить число запросов и МОГУТ улучшить производительность, если:
1. в обрабатываемой таблице нет переопределенных методов insert, update, delete соответственно
2. обрабатываемая таблица не включена в RLS
3. обрабатываемая таблица не содержит deleteAction (для удаления)

Да, можно отключить эти факторы при помощи skip-методов.
Но отключение переопределенных методов чревато тем, что логическая целостность базы нарушится.

Подробнее см хелп, ключевая фраза "What prevents fast SQL operations?"

Кроме того, подобные операции может быть и повышают производительность, но гарантировано уменьшают наглядность и юзабилити.
Обычно при длительной обработке данных показывают прогресс-бар, который показывает сколько процентов осталось.
Групповые операции ничего не показывают. Если групповая операция выполняется несколько минут, то вы не знаете: повисла она, заблокирована или таки выполняется.

И кроме того, групповые операции блокируют ВСЕ обрабатываемые записи за один раз. А обработка каждой записи, при правильном написании, блокирует только обрабатываемую запись. См. aEremenko: Ресурс заблокирован, ждите...

Ну, и напоследок, групповые операции не позволяют работать с критериями из query. Что напрочь лишает их полезность, если пользователь может задавать критерии со спец-символами http://axapta.mazzy.ru/lib/search/

В общем, групповые операции дело хорошее.
Но у них тоже есть минусы.

Цитата:
Сообщение от Blog bot Посмотреть сообщение
Например, возьмем код:
X++:
      while select * from custCollectionLetterTrans 
              where custCollectionLetterTrans.CollectionLetterNum == this.CollectionLetterNum 
                 && custCollectionLetterTrans.AccountNum          == this.AccountNum 
                 && custCollectionLetterTrans.CollectionLetterIssued 
        { 
             custTrans = CustTrans::find(custCollectionLetterTrans.CustTransId, true); 
              custTrans.CollectionLetterCode = custCollectionLetterTrans.CollectionLetterCode; 
              custTrans.update(); 
         }
Это отвратительный код, за который надо штрафовать программиста и снижать его зарплату. Надеюсь, что этот код упрощен только для демонстрационных целей

Более правильный код:

X++:
SysProgressOperation progress;
;
      select count(recid) from custCollectionLetterTrans 
              where custCollectionLetterTrans.CollectionLetterNum == this.CollectionLetterNum 
                 && custCollectionLetterTrans.AccountNum          == this.AccountNum 
                 && custCollectionLetterTrans.CollectionLetterIssued;
      progress = SysProgressOperation::newGeneral('','',custCollectionLetterTrans.recid);


      while select * from custCollectionLetterTrans 
              where custCollectionLetterTrans.CollectionLetterNum == this.CollectionLetterNum 
                 && custCollectionLetterTrans.AccountNum          == this.AccountNum 
                 && custCollectionLetterTrans.CollectionLetterIssued 
        { 
              ttsbegin;
             custTrans = CustTrans::find(custCollectionLetterTrans.CustTransId, true); 
              custTrans.CollectionLetterCode = custCollectionLetterTrans.CollectionLetterCode; 
              custTrans.update(); 
              ttscommit;

              progress.inccount();
         }
Еще более правильным было бы создание запроса для таблицы и код:
X++:
SysProgressOperation progress;
Query q;
QueryBuildDataSource = qbds;
QueryRun qr;
;
q = new Query(queryStr(mySupercustCollectionLetterTransQuery));
qbds = q.datasourcetable(tablenum(custCollectionLetterTrans));
SysQuery::findOrCreateRange(qbds,fieldnum(custCollectionLetterTrans,CollectionLetterNum ).value(this.CollectionLetterNum);
SysQuery::findOrCreateRange(qbds,fieldnum(custCollectionLetterTrans,AccountNum).value(this.AccountNum );
SysQuery::findOrCreateRange(qbds,fieldnum(custCollectionLetterTrans,CollectionLetterIssued).value(SysQuery::notEmptyString());

qr = new QueryRun(q);
progress = SysProgressOperation::newGeneral('','',SysQuery::CountTotal(qr));


while( qr.next() )
{ 
    custCollectionLetterTrans = qr.getTable(tablenum(custCollectionLetterTrans));

    ttsbegin;
    custTrans = CustTrans::find(custCollectionLetterTrans.CustTransId, true); 
    custTrans.CollectionLetterCode = custCollectionLetterTrans.CollectionLetterCode; 
    custTrans.update(); 
    ttscommit;

    progress.inccount();
}
Этот код позволяет:
1. отделить запрос и процесс его оптимизации от программирования.
2. позволяет работать с пользовательскими критериями
3. полностью совместим со всей функциональностью форм и отчетов
4. полностью совместим с пакетной обработкой
5. информирует пользователя о ходе выполнения.

Поэтому... Если уж начали двигаться в сторону групповых операций... Если это возможно.... Нужен не update_recordset, а дополнительный режим групповой обработки для Query.
__________________
полезное на axForum, github, vk, coub.
За это сообщение автора поблагодарили: Recoilme (-2), kashperuk (3), oip (9).