Skip to main content

All about queries

The query object model contains classes to define and run a query. These objects are used to define the query data source, the fields returned, record ranges and relations to child data sources. The following illustration shows the object model.
The query components shown in the previous figure are system classes. The query classes are more visible when you create a dynamic query in code, but they are also used behind the scenes when you create a static query in the AOT.







System class
Description

QueryRun
Executes the query and fetches the data.
Query
The top level of the query definition. This class holds some properties itself and has one or more related data sources.
QueryBuildDataSource
Defines access to a single data source in the query. If more than one data source exists at the same level in a query, they result in separate SQL statements that are executed sequentially. If one data source exists as a child of another data source, a join is created between the two data sources.
QueryBuildFieldList
Defines which fields are returned from the database. The default is that the field list is dynamic, which returns all fields from the data source table, map, or view. Each data source has only one QueryBuildFieldList object, which contains information on all selected fields. It’s possible to specify aggregate functions like SUM, COUNT, and AVG on the field list object.
QueryBuildRange
Defines a subset of records returned based on a single field. A range is translated into a WHERE clause in the query SQL statement. If more than one field is used to limit the query (WHERE clause), the data source will contain more than one range.
QueryBuildDynalink
Contains information regarding a relation (limitation) to an external record. When the query is run, this information is converted to additional entries in the WHERE clause of the query SQL statement. Can only exist on the parent data source of a query. The function is used by forms, when two data sources are synchronized. Then the child data source will contain a dynalink or dynalinks to the parent data source. The function is used even if the two data sources are placed in two different forms but are still synchronized.
QueryBuildLink
Specifies the relation between the two data sources in the join. Can only exist on a child data source.

[Source for above text: Microsoft Dyanmics AX 4.0 Developer Guide]
Below is a job that can illustrate usage different query framework classes
static void queryCreation(Args _args)
{
Query query = new Query(‘MyQuery’);
QueryBuildDataSource custTableQBDS, custTransQBDS;
QueryBuildRange qbr1, qbr2;
QueryBuildFieldList qbFl, qbF2, qbF3;
QueryBuildLink qbl;
QueryBuildDynalink qbdl;
QueryRun qr;
CustTable custTable;
CustTrans custTrans;
LedgerTrans ledgerTrans;
;
custTableQBDS = query.addDataSource(tablenum(custTable));
//This will enable you to add the fields you like
//If dynamics is yes all the fields will be automatically added

custTableQBDS.fields().dynamic(NoYes::No);
qbFl = custTableQBDS.fields().addField(fieldNum(CustTable, AccountNum));
qbF2 = custTableQBDS.fields().addField(fieldNum(CustTable, InvoiceAccount));
qbF3 = custTableQBDS.fields().addField(fieldNum(CustTable, CustGroup));
//Adding Ranges
qbr1 = query.dataSourceTable(tableNum(CustTable)).addRange(fieldNum(CustTable, AccountNum));
qbr2 = query.dataSourceTable(tableNum(CustTable)).addRange(fieldNum(CustTable, InvoiceAccount));
qbr1.value(SysQuery::value(’4011′));
qbr2.value(SysQuery::value(’4010′));
//Add child data source to main datasource
custTransQBDS = custTableQBDS.addDataSource(tableNum(CustTrans));
//Two ways to add relation
//First – This may not work in all the scenarios
custTransQBDS.relations(true);
//Second – QueryBuildLink
qbl = custTransQBDS.addLink(fieldNum(CustTable, AccountNum), fieldNum(CustTrans, AccountNum));
SetPrefix (‘Queries’);
setPrefix (‘Dynalinks’);
qr = new QueryRun(query);
setPrefix (‘Without’);
while (qr.next())
{
if (qr.changed(tableNum(CustTable)))
{
custTable = qr.get(tableNum(CustTable));
}
setPrefix (‘Customer – ‘ + custTable.AccountNum);
if (qr.changed(tableNum(CustTrans)))
{
custTrans = qr.get(tableNum(CustTrans));
info(custTrans.Voucher);
}
}
//Dynalink test so run the loop after dynamically linking with a table select firstonly ledgerTrans where ledgerTrans.Voucher == ‘US_800006′ &&
ledgerTrans.AccountNum == ’130100′;
custTransQBDS.addDynalink(fieldNum(CustTrans, Voucher), ledgerTrans, fieldNum(LedgerTrans, Voucher));
custTransQBDS.addDynalink(fieldNum(CustTrans, TransDate), ledgerTrans, fieldNum(LedgerTrans, TransDate));
qr = new QueryRun(query);
setPrefix(‘Dynalinks’);
setPrefix (‘With’);
while (qr.next())
{
if (qr.changed(tableNum(CustTable)))
{
custTable = qr.get(tableNum(CustTable));
}
setPrefix (‘Customer – ‘ + custTable.AccountNum);
if (qr.changed(tableNum(CustTrans)))
{
custTrans = qr.get(tableNum(CustTrans));
info(custTrans.Voucher);
}
}
}

Popular posts from this blog

Mark All for Open Cust Trans and Open Vend Trans

We have situations where there are lots of open transactions that need to be settled against each other. This can be the case if auto settlement is turned off. One solution is to add a "Mark All" button to the custOpenTrans or vendOpenTrans forms. This button "checks" the mark checkbox on every line. The user can then uncheck several lines if needed and Update to settle the lines. The code below is an example of what we used on the open vendor transaction screen. The code is very similar on the AR side. One note: I used vendTable.AccountNum in the code below. That should be generalized to work with any buffer that is passed into the open trans form. void customMarkAll() { VendTransOpen localVendTransOpen; VendTrans localVendTrans; container conSum; int linesProcessed; ; //show wait cursor startLengthyOperation(); element.lock(); //remove all prior markings specOffsetVoucher.deleteSpe...

Print Report in Microsoft Dynamics AX 2009 through X++

I am trying to print sales confirmation report on a button click which I have added on Sales Order Detail form in Microsoft Dynamics AX 2009. On click event of that button, I have written following code: void clicked() {     Args                args;     ReportRun           reportRun;     SalesFormLetter     salesFormLetter;     PrintJobSettings    printJobSettings;     CustConfirmJour     custConfirmJour;     RecordSortedList    list                = new RecordSortedList(55);     SalesTable          salesTableUpdate;     ;     SELEC...

Creating Free Text Invoice through X++ code

Job: Calling class from job to run the class public void freeTextInvoicePostTestJob() { Dialog dialog; DialogField dlgCustAcc; DialogGroup dialogPeriodLengthGroup, dialogPeriodLengthGroup1; DialogField dlgLedgerAcc; ; dialog = new Dialog("Free-Text Invoice"); dialogPeriodLengthGroup1 = dialog.addGroup('Cust Table'); dlgCustAcc = dialog.addField(typeid(CustAccount)); dialogPeriodLengthGroup = dialog.addGroup('Ledger Table'); dlgLedgerAcc = dialog.addField(typeid(LedgerAccount)); if(dialog.run()) { if(dlgCustAcc.value() && dlgLedgerAcc.value() != '') FreeTxtInvoiceCreatePost::main(dlgCustAcc.value(), dlgLedgerAcc.value()); else throw error(strfmt("Either CustAccount or LedgerAccount info is missing.")); } } Class: Which creates the free text invoice class FreeTxtInvoiceCreatePost { } static void main(CustAccount _custAccount, LedgerAccount _ledgerAccount) { CustInvoiceTable custInvoiceTable; ...