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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 03.07.2013, 11:07   #1  
Мартынов Дмитрий is offline
Мартынов Дмитрий
Участник
 
236 / 66 (3) ++++
Регистрация: 02.02.2004
Адрес: г. Москва
? Удаление записей с собираемым условием как в query
Продолжая тему т.н. "динамического программирования" (подходящий правильный термин ищем здесь)

Если нужно сделать выборку по программно-собираемому условию, то все знаю, что надо использовать классы QueryRun, Query, QueryBuildRange и т.д.

А если нужно удалить записи по динамическому условию. Я не знаю такого механизма, ни когда его не встречал. Точнее есть такие механизмы, но они не такие красивые как Query.
1. Один такой механизм применяется в браузере таблиц
2. Еще можно сформировать и отправить прямой запрос на SQL с помощью всяких коннекторов.

А хочется чего то правильного в рамках общей логики системы...
Старый 03.07.2013, 11:22   #2  
ice is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,731 / 406 (17) +++++++
Регистрация: 23.03.2006
в чем проблема то? выбирайте записи и удаляйте
Старый 03.07.2013, 11:31   #3  
Мартынов Дмитрий is offline
Мартынов Дмитрий
Участник
 
236 / 66 (3) ++++
Регистрация: 02.02.2004
Адрес: г. Москва
Цитата:
Сообщение от ice Посмотреть сообщение
в чем проблема то? выбирайте записи и удаляйте
Я не нашел в QueryRun метода УДАЛИТЬ записи по запросу. Там только метод ВЫБРАТЬ...
Старый 03.07.2013, 11:38   #4  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
873 / 649 (23) +++++++
Регистрация: 14.10.2004
X++:
while (queryRun.next())
{
    salesTable = queryRun.get(tableNum(SalesTable));
    ttsbegin;
    updSalesTable = SalesTable::find(salesTable.SalesId, true);
    if (updSalesTable.RecId)
        updSalesTable.delete();
    ttscommit;
}
За это сообщение автора поблагодарили: Мартынов Дмитрий (1).
Старый 03.07.2013, 12:09   #5  
Мартынов Дмитрий is offline
Мартынов Дмитрий
Участник
 
236 / 66 (3) ++++
Регистрация: 02.02.2004
Адрес: г. Москва
Цитата:
Сообщение от Ace of Database Посмотреть сообщение
X++:
while (queryRun.next())
{
    salesTable = queryRun.get(tableNum(SalesTable));
    ttsbegin;
    updSalesTable = SalesTable::find(salesTable.SalesId, true);
    if (updSalesTable.RecId)
        updSalesTable.delete();
    ttscommit;
}

А без циклов что нибудь есть?
Мы же можем написать
X++:
delete_from salesTable where ...
И удалить все одной командой. А если еще и добавить перед этим
X++:
    salesTable.skipEvents(true);
    salesTable.skipDataMethods(true);
То будет все еще быстрее. Правда надо не забыть отработать то, что было в методах и тегах удаления другими способами...

Хочется чего то такого (следующий код является фантазией по этому во избежании путаницы ставлю тег PHP++):
PHP код:
    queryRun.skipEvents(true);
    
queryRun.skipDataMethods(true);
    
queryRun.deleteRecords(); 
Старый 03.07.2013, 13:35   #6  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от Мартынов Дмитрий Посмотреть сообщение
А без циклов что нибудь есть? Мы же можем написать
X++:
delete_from salesTable where ...
И удалить все одной командой.
Если предположить, что за раз будет удаляться не очень много записей - в пределах 10 тысяч, допустим (иначе транзакционный лог раздуется, и транзакция удаления записей будет достаточно долго отрабатывать) - то можно использовать такой подход: создать Query для выбора RecId удаляемых записей, при этом записи фильтровать по произвольным параметризируемым критериям, затем полученные RecId записать во вспомогательную таблицу (по аналогии с тем, как работает класс RecordReferenceList_RU) и в delete_from приджойнить ее к таблице, записи из которой удаляются.
За это сообщение автора поблагодарили: Мартынов Дмитрий (1).
Старый 03.07.2013, 14:13   #7  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Мартынов Дмитрий Посмотреть сообщение
А без циклов что нибудь есть?
...
То будет все еще быстрее.
Не совсем так.
ты говоришь об ОДНОМ клиенте. А Аксапта - сетевая система.

Обрати внимание на вложенную транзакцию, которая присутствует в предлагаемом тебе примере. В цикле с маленькими транзакциями блокировки не эскалируются. Время, на которое блокируется каждая запись минимально.

delete_from будет делаться в одной транзакции. Следовательно велика вероятность эскалации блокировок. Кроме того, все затрагиваемые записи будут заблокированы до окончания транакции. Следовательно общая производительность скорее всего будет ниже из-за блокировок, а вероятность deadlock'ов сильно возрастает.

===============
Где-то в книжках по аксапте читал, что когда вводили групповые операции delete_from, updaterecordset и insertrecordset крепко думали об этом. Суть - в операторах за быстродействие полностью отвечает программист. И это его непосредственная задача думать о производительности. Query, в отличие от оператора, может корректироваться пользователем. Поэтому, христос его знает, что может ввести туда пользователь... и условия по полям без индекса, и дополнительные join... поэтому вводить такую фичу в Query не стали.
За это сообщение автора поблагодарили: Мартынов Дмитрий (1).
Старый 03.07.2013, 15:10   #8  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
873 / 649 (23) +++++++
Регистрация: 14.10.2004
Удаление - это очень опасная операция. Если вы для SalesTable поставите skipDataMethods(true), то у вас останутся строки заказов без шапки и останутся складские проводки. Я за свою жизнь наверное ни разу не использовал skipDataMethods(true)
skipDataMethods(true) можно использовать только в случаях, когда требуется администрирование данных, а не обычная ежедневная работа в штатном режиме. Но для администрирования данных лучше уж работать напрямую с SQL.
Старый 03.07.2013, 17:01   #9  
fed is offline
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,907 / 5717 (196) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
Я пожалуй добавлю еще одну технику из этой же оперы. Допустим нам надо сделать обновление большого числа записей по хитрому алкогоритму. Поскольку хитрый алкогоритм в виде update_recordset не переписать, я иногда, когда нужна максимальная производительность любой ценой, делаю так:
1. Создаю таблицу с полями updateId (GUID), Key (может быть refRecId или salesId или что-то подобное), и полями newVal1,newVal2,newVal3 и тп
2. Далее, в цикле, вместо обновления записей основной таблицы, через RecordInsertList вставляю новые записи, засовывая в ее поля ключи основной таблицы и значимые поля с новыми значениями.
3. Затем, после recordInsertList.insertDatabase() пишу
X++:
update_recordset mainTable 
setting field1=tempTable.NewValue1,field2=tempTable.NewValue2
join tmpValuesTable
where tmpValuesTable.updateId==myGuid
&& tmpValuesTable.key=mainTable.key
Разумеется в силе остаются соображения насчет параллелизма, предотвращения конфликтов обновления, блокировок и тп. Тем не менее, в простых случаях выигрыш перед while select.. table.update() может быть раза в 4...

Последний раз редактировалось fed; 03.07.2013 в 17:12. Причина: Стиль
За это сообщение автора поблагодарили: Мартынов Дмитрий (1), coolibin (2).
Старый 03.07.2013, 17:37   #10  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от fed Посмотреть сообщение
Тем не менее, в простых случаях выигрыш перед while select.. table.update() может быть раза в 4...
угу. в монопольном доступе.
Старый 03.07.2013, 17:48   #11  
fed is offline
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,907 / 5717 (196) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
Цитата:
Сообщение от mazzy Посмотреть сообщение
угу. в монопольном доступе.
Не спорю. Но в операциях типа закрытия месяца (в которых записи уже не должны пользователи трогать) - очень даже неплохо применимо...
За это сообщение автора поблагодарили: mazzy (2).
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
AIF: OData Query Service Blog bot DAX Blogs 0 24.08.2011 09:11
Массовое удаление записей через CCADOConnection Shirmin Oleg DAX: Программирование 68 04.05.2010 15:49
Программное удаление data source из query erudit DAX: Программирование 3 21.04.2010 18:11
AX2009: Как создать Query со сложним условием t1.f1 = str(t2.f2) ? andriy_s DAX: Программирование 5 01.09.2009 16:23
Удаление записей из InventDim и SalesTable DreamCreator DAX: Программирование 4 08.12.2004 17:23

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

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

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