Der Umgang mit Queries ist auch in Microsoft Dynamics AX sehr einfach, sofern man mit den Objekten vertraut ist.
Angefangen mit einem einfachen Query, der kann entweder auf Basis eines im AOT (Query) definierten Querys erzeugt werden
oder auch komplett neu mit x++ erzeugt werden kann.
Folgende Okjekte werden verwendet
Query (Abfrage)
QueryRun (führt die Abfrage aus)
QueryBuildDataSource (DataSource in der Abfrage)
QueryBuildRange (Range (Einschränkung) auf der DataSource)
Kurzes Beispiel:
Das Ergebniss ist die Ausgabe alle Artikel bei denen die Artikelgruppe "Teile" hinterlegt wurde.
Auf Basis eines im AOT definierten Queries
//Ein neues Query Objekt, verwendet wird die Query (Im AOT) "InventTable"
Query queryInventTable = new Query(querystr(InventTable));
QueryRun queryRun;
QueryBuildDataSource queryDS;
QueryBuildRange queryRange;
InventTable inventTable;
;
// Datasource zuordnen
queryDS = queryInventTable.dataSourceTable(tablenum(InventTable));
// Prüfen ob Range schon vorhanden
if (queryDS.findRange(fieldnum(InventTable, ItemGroupID)))
queryRange = queryDS.findRange(fieldnum(InventTable, ItemGroupID));
else
queryRange = queryDS.addRange(fieldnum(InventTable, ItemGroupID));
queryRange.value("Teile");
// queryRun mit dem aktuell neu erstellen query auf Basis des Queries "InventTable" erzeugen
queryRun = new QueryRun(queryInventTable);
// alle Datensätze ausgeben
while (queryRun.next())
{
inventTable = queryRun.get(tablenum(InventTable));
print InventTable.ItemID;
}
pause;
Komplett in X++ definierte Query
//Ein neues leeres Query Objekt
Query query = new Query();
QueryRun queryRun;
QueryBuildDataSource queryDS;
QueryBuildRange queryRange;
InventTable inventTable;
;
// Datasource (Tabelle InventTable) hinzufügen
queryDS = query.addDataSource(tablenum(InventTable));
// Range definineren
queryRange = queryDS.addRange(fieldnum(InventTable, ItemGroupID));
queryRange.value("Teile");
// alternative
// Range definineren
query.dataSourceTable(tablenum(InventTable)).addRange(fieldnum(InventTable, ItemGroupID)).value("Teile");
// queryRun mit dem aktuell neu erstellen query erzeugen
queryRun = new QueryRun(query);
// alle Datensätze ausgeben
while (queryRun.next())
{
inventTable = queryRun.get(tablenum(InventTable));
print InventTable.ItemID;
}
Bei diesem einfachen Query macht es keinen Unterschied ob im AOT definiertes Query verwendet wird, oder ob man die definition komplett in X++ vornimmt.
Benutzt man ein Query das schon irgendwo definiert wurde und möchte dieses verwenden, sollte man immer auf schon vorhandene Objekte (siehe findRange)
zurückgegriffen werden sofern schon vorhanden.Ansonsten fügt man immer wieder dasselbe Objekt hinzu, bei Ranges hat das dann zufolge, das in der Abfrage nicht mehr auf die aktuell
definierte Range zurückgegriffen wird, sondern auf alle davor definieren Ranges ebenfalls.
Das kann sehr gut in dem unterem Beispiel getestet werden, indem man einfach eine neue Range auf demselben Feld wie schon zuvor definiert hinzufügt und eine anderen
Wert festlegt.
Das Ergebnis ist die Ausgabe alle Artikel bei denen die Artikelgruppe "Teile" und "Lampen" hinterlegt wurde.
// Range definineren
queryRange = queryDS.addRange(fieldnum(InventTable, ItemGroupID));
queryRange.value("Teile");
// Neue Range auf demselben Feld. ein andere Wert wird festgelegt
queryRange = queryDS.addRange(fieldnum(InventTable, ItemGroupID));
queryRange.value("Lampen");
Der Zugriff auf einzelne Elemente (wie DataSource oder Range) der Query ist jeweils immer gleich. Bei der DataSource sollte immer beachtet werden, dass es ggf. mehrere Objekte vom selben Typ (Tabelle) geben könnte. Ein gutes Beispiel hierfür sind wieder die Artikel (InventTable) mit den drei verknüpften Lagermodulparameter (InventTableModule). Wir hierbei der Zugriff auf die DataSource über tablenum gesteuert erhält man immer ein und dieselbe DataSource und nicht wie evtl gewünscht alle drei DataSources.
Der Zugriff sollte dann über den DataSource-Namen erfolgen, der immer eindeutig ist, sogar dann wenn das hinzufügen per x++ geschieht.
Hinzufügen von drei neuen DataSources und der Zugriff auf jeder DataSource der aktuellen Abfragen, inkl. Ausgabe des Namen
Query query = new Query();
counter dsCount;
;
// Datasource (Tabelle InventTable) hinzufügen
queryDSInvent= query.addDataSource(tablenum(InventTable));
//neue relation auf Lagermodulparameter (3mal)
queryDSInvent.addDataSource(tablenum(InventTableModule)).relations(true);
queryDSInvent.addDataSource(tablenum(InventTableModule)).relations(true);
queryDSInvent.addDataSource(tablenum(InventTableModule)).relations(true);
/ Ausgabe aller DataSources die im aktuellen Query vorhanden sind
for (dsCount = 1; dsCount <= query.dataSourceCount(); dsCount++)
{
print query.dataSourceNo(dsCount).name();
}
pause;
Wird der DataSource kein Name zugewiesen erzeugt Dynamics AX automatisch einen eindeutigen Namen (Tabellenname_Zähler).
Hinterlegt man nun noch bei den LagerModulparametern eine Range (Verkauf, Einkauf, Lager) auf den Lagertyp hat man im groben die Standardquery (es fehlt noch die Lagerortverwaltung Tabelle) der Artikelmaske nachgebaut.
// Lager
queryDS = queryDSInvent.addDataSource(tablenum(InventTableModule));
queryDS.relations(true);
queryDS.joinMode(JoinMode::InnerJoin);
queryRange = queryDs.addRange(fieldnum(InventTableModule,ModuleType));
queryRange.value(queryValue(ModuleInventPurchSales::Invent));
Prinzipiell kann man mit dieser Query auch die Query auf der Maske InventTable überladen. Diee Anzeige der Artikel klappt weiterhin wunderbar
nur die Referenzen auf die zusätzlichen FormDataSources geht hierbei verloren. Dadurch funktioniert die Anzeige und Bearbeitung der Daten aus diesen FormDataSources dann nicht mehr.
Spasseshalber aber noch der Quellcode, der auch die Query der Form überlädt.
Job_QueryEinfachFormRun.xpo (3,05 KB)