MS Dynamics AX 2012. Копирование критериев запроса с помощью класса SysQuery

Метод mergeRanges

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

static void mergeRanges(
        Query       	q,
        Query       	initQ,
        int         	initQdsNo 	       = 1,
        boolean     	alwaysAddDatasource    = false,
        boolean     	addSameFieldRange      = true)

Метод имеет входные параметры, первые два из которых обязательно необходимо указать.

Параметр q – передаем запрос, в который мы будем добавлять критерии. Он же приемник.

Параметр initQ – передаем запрос, из которого будет брать критерии. Он же источник.

Остальные по желанию:

initQdsNo – номер таблицы в источнике, из которой будем брать критерии. Таким образом, чтобы взять критерии со всех таблиц в запросе, необходимо использовать цикл и вызывать метод в нем.

alwaysAddDatasource – параметр True, то если в приемнике не будет такой же таблицы, как в источнике, то она будет добавлена в приемник. Но надо понимать, что она будет добавлена в запрос как отдельная таблица, без привязки, даже если привязка была в источнике.

Если параметр будет установлен False, то возможны две ситуации.

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

Вторая ситуация, если общее количество таблиц в приемнике меньше текущей порядковой таблицы в источнике, то тогда в запрос принудительно будет добавлен новый источник данных. Например, приемник состоит из 3-х таблиц, а источник из 4-х. Предполагаем, что первые 3 таблицы идентичны, то, когда будет обрабатываться 4-я таблица источника, то в приемнике, она будет добавлена принудительно, но без привязки, даже если такая была в источнике.

addSameFieldRange – параметр указывает, на возможность добавлять критерий, если такой в приемнике уже существует. Критерий будет добавлен через ИЛИ.

Пример:

query1 			= new Query();
qbdsInventTable1 	= query1.addDataSource(tableNum(InventTable));
qbdsWHSInventTable1 	= qbdsInventTable1.addDataSource(tableNum(WHSInventTable));

query2 = new Query(query1);    

qbdsInventTable1.addRange(fieldNum(InventTable, ItemId)).value(SysQuery::value('testAAA'));
qbdsWHSInventTable1.addRange(fieldNum(WHSInventTable, FilterCode)).value(SysQuery::value('testGroupAAA'));
    
qbdsInventTable2 = query2.dataSourceTable(tableNum(InventTable));
qbdsInventTable2.addRange(fieldNum(InventTable, ItemId)).value(SysQuery::value('testBBB'));
qbdsWHSInventTable2 = query2.dataSourceTable (tableNum(WHSInventTable));
qbdsWHSInventTable2.addRange(fieldNum(WHSInventTable, FilterCode)).value(SysQuery::value('testGroupBBB'));

info('before');
info(new QueryRun(query2).toString());
    
for (idx = 1; idx <= query1.dataSourceCount(); idx ++)
{
    SysQuery::mergeRanges(query2, query1, idx, false, true);
}
    
info('after');
info(new QueryRun(query2).toString());

Результат:

--before
SELECT * FROM InventTable(InventTable_1) WHERE ((ItemId = N'testBBB')) JOIN * FROM WHSInventTable(WHSInventTable_1) ON InventTable.ItemId = WHSInventTable.ItemId AND ((FilterCode = N'testGroupBBB'))

--after
SELECT * FROM InventTable(InventTable_1) WHERE ((ItemId = N'testBBB') OR (ItemId = N'testAAA')) JOIN * FROM WHSInventTable(WHSInventTable_1) ON InventTable.ItemId = WHSInventTable.ItemId AND ((FilterCode = N'testGroupBBB') OR (FilterCode = N'testGroupAAA'))

В результате видим, что теперь в приемнике появились дополнительные критерии отбора.

Следует учитывать, что работа ведется по конкретной таблице, без привязки к другим таблицам внутри запроса. Т.е. какой индексный номер указали, с таким номером из запроса будет взята таблица и только с ней будет вестись работа.

Пример:

query1 			= new Query();
qbdsInventTable1 	= query1.addDataSource(tableNum(InventTable));
qbdsWHSInventTable1 	= qbdsInventTable1.addDataSource(tableNum(WHSInventTable));
qbdsInventTable1.addRange(fieldNum(InventTable, ItemId)).value(SysQuery::value('testAAA'));
qbdsWHSInventTable1.addRange(fieldNum(WHSInventTable, FilterCode)).value(SysQuery::value('testGroupAAA'));

query2 		    	= new Query();        
qbdsInventTable2 	= query2.addDataSource(tableNum(InventTable));
qbdsInventTable2.addRange(fieldNum(InventTable, ItemId)).value(SysQuery::value('testBBB'));
qbdsWHSInventTable2 = query2. addDataSource (tableNum(WHSInventTable));
qbdsWHSInventTable2.addRange(fieldNum(WHSInventTable, FilterCode)).value(SysQuery::value('testGroupBBB'));

info('before');
info(new QueryRun(query2).toString());
    
for (idx = 1; idx <= query1.dataSourceCount(); idx ++)
{
    SysQuery::mergeRanges(query2, query1, idx, false, true);
}
    
info('after');
info(new QueryRun(query2).toString());

Результат:

--before
SELECT * FROM InventTable(InventTable_1) WHERE ((ItemId = N'testBBB')); SELECT * FROM WHSInventTable(WHSInventTable_1) WHERE ((FilterCode = N'testGroupBBB'))

--after
SELECT * FROM InventTable(InventTable_1) WHERE ((ItemId = N'testBBB') OR (ItemId = N'testAAA')); SELECT * FROM WHSInventTable(WHSInventTable_1) WHERE ((FilterCode = N'testGroupBBB') OR (FilterCode = N'testGroupAAA'))

Как было сказано выше, если процессе копирования критериев будет добавлена новая таблица в запрос, то она будет представлять из себя отдельный источник данных. Но может быть необходимость присоединить новую таблицу к существующей таблице, тогда вместо метода mergeRanges необходимо воспользоваться методом copyDataSource.

public static void copyDataSource(
        QueryBuildDataSource    _fromDS,
        QueryBuildDataSource 	_toDS,
        boolean 		_recurse = true)

Первые два параметра понятны по смыслу.

Параметр _recurse – отвечает за копирование из подчинённых родительскому источников _fromDS.

Пример:

query1 = new Query();
qbdsInventTable1 = query1.addDataSource(tableNum(InventTable));
qbdsInventTable1.addRange(fieldNum(InventTable, ItemId)).value(SysQuery::value('testAAA'));

qbdsWHSInventTable1 = qbdsInventTable1.addDataSource(tableNum(WHSInventTable));
bdsWHSInventTable1.addRange(fieldNum(WHSInventTable, FilterCode)).value(SysQuery::value('testGroupAAA'));
    
query2 = new Query();
qbdsInventTable2 = query2.addDataSource(tableNum(InventTable));
qbdsInventTable2.addRange(fieldNum(InventTable, ItemId)).value(SysQuery::value('testBBB'));
    
info('before');
info(new QueryRun(query2).toString());
    
for (idx = 1; idx <= query1.dataSourceCount(); idx ++)
{
        qbdsCommon = query2.dataSourceTable(query1.dataSourceNo(idx).table());
        if (!qbdsCommon)
        {
            qbdsSourceParent = query1.dataSourceNo(idx).parentDataSource();
            if (qbdsSourceParent)
            {
                qbdsCommonParent = query2.dataSourceTable(qbdsSourceParent.table());
                if (qbdsCommonParent)
                {
                    qbdsCommon = qbdsCommonParent.addDataSource(query1.dataSourceNo(idx).table());
                }
            }
            
            if (!qbdsCommon)
            {
                qbdsCommon = query2.addDataSource(query1.dataSourceNo(idx).table());
            }
            
            SysQuery::copyDataSource(query1.dataSourceNo(idx), qbdsCommon, false);         
        }
        else
        {
            SysQuery::mergeRanges(query2, query1, idx, false, true);
        }
}
    
info('after');
info(new QueryRun(query2).toString());

Результат:

--before
SELECT * FROM InventTable(InventTable_1) WHERE ((ItemId = N'testBBB'))

--after
SELECT * FROM InventTable(InventTable_1) WHERE ((ItemId = N'testBBB') OR (ItemId = N'testAAA')) JOIN * FROM WHSInventTable(WHSInventTable_1) ON ((FilterCode = N'testGroupAAA'))

В результате видим, что в приемнике, появился новый источник данных, с критериями из источника.

mergeFilter

Метод используется для копирования критериев, которые заданы на формы.

public static void mergeFilters(	
        Query      _sourceQuery,
        Query      _targetQuery,
        int        _sourceQueryDataSourceIndex 	       = 1,
        boolean    _alwaysAddDatasource 	       = false,
        boolean    _doNotAddQueryFilterForSameField    = false)

Смысл работы такой же, как и у функции mergeRanges. Только в первом случае ведется работа с объектами QueryBuildRange, а здесь с объектами QueryFilter.

microsoft.com

Comments

So empty here ... leave a comment!

Добавить комментарий

Sidebar