Dynamics AX Blog - Dynamics AX 2012 - Beiträge von 2014 - Seite 7

RSS-Feed dieser Version
AX 2012: Ausführen einer statischen Klassen-Methode in der CIL
15.03.2014Microsoft Dynamics AX (Axapta)
Mit Hilfe der nachstehenden Klasse möchte ich zeigen, wie man in Dynamic AX 2012 X++ Code als CIL ausführt. Die Klasse MyDemoClass enthält eine statische Methode countSalesRecords() welche die eigentliche Logik enthält.
Zu beachten sind vor allem die Modifier der jeweiligen Methoden sowie das Parameter-Profil der Methode countSalesRecordsIL() (ein- und ausgehender Container). Hätte die Methode keinen eingehenden Container als Parameter, würde AX behaupten, die Methode nicht zu kennen:
Nachdem man die Klasse erstellt und die CIL inkrementell kompiliert hat, kann man die Klasse per rechter Maustaste ausführen. Dadurch wird die main()-Methode aufgerufen welche die Logik der Methode countSalesRecords() auf die altbewährte Art & Weise aufruft und zusätzlich in der CLR ausführt. Vorausgesetzt natürlich der Benutzer hat in seinen Benutzer-Optionen die Option Geschäftliche Arbeitsgänge in CIL ausführen aktiviert! class MyDemoClass { }
public server static counter countSalesRecords(SalesStatus _salesStatus) { Query query; QueryBuildDataSource qbds_salesTable; QueryBuildDataSource qbds_salesLine; QueryRun queryRun; Counter r; setPrefix(strFmt("isCLRSession: %1", enum2str(xSession::isCLRSession()))); setPrefix(enum2str(_salesStatus)); query = new query(); qbds_salesTable = query.addDataSource(tableNum(salesTable)); qbds_salesTable.addSelectionField(fieldNum(salesTable, RecId)); qbds_salesLine = qbds_salesTable.addDataSource(tableNum(salesLine)); qbds_salesLine.addSelectionField(fieldNum(salesLine, RecId)); qbds_salesLine.joinMode(JoinMode::InnerJoin); qbds_salesLine.relations(true); SysQuery::findOrCreateRange(qbds_salesTable, fieldNum(SalesTable, SalesStatus)).value(queryValue(_salesStatus)); queryRun = new queryRun(query); while(queryRun.next()) { r++; } info(strFmt("Records: %1", r)); return r; }
private server static container countSalesRecordsIL(container _con) { SalesStatus salesStatus; Counter c; container cReturn; salesStatus = conPeek(_con, 1); // Call method and get it's return value c = MyDemoClass::countSalesRecords(salesStatus); return conPoke(cReturn, 1, c); }
public server static counter countSalesRecordsWrapper(SalesStatus _salesStatus) // Same parameter-profile as method, which is called in CIL { container resultContainer; Counter c; new XppILExecutePermission().assert(); resultContainer = Global::runClassMethodIL(classStr(MyDemoClass), staticMethodStr(MyDemoClass, countSalesRecordsIL), [_salesStatus]); CodeAccessPermission::revertAssert(); // Get return value through resultContainer c = conPeek(resultContainer, 1); return c; }
public static server void main(Args _args) { setPrefix("MyDemoClass"); MyDemoClass::countSalesRecords(SalesStatus::Invoiced); MyDemoClass::countSalesRecordsWrapper(SalesStatus::Backorder); } |
Werte eines Base-Enums durchlaufenSysDictEnum SysDictEnum = new SysDictEnum(enumNum(SalesStatus)); int i; for (i=0;i<SysDictEnum.values();i++) { info(SysDictEnum.index2Label(i)); } |
SQL-Fehler beim Öffnen/Synchronisieren einer TabelleTritt beim Öffnen oder Synchronisieren einer - meist neu erstellten - Tabelle der folgende Fehler auf
so kann die Ursache sein, daß die Tabelle ein Feld enthält, dessen Name ein "Reserved Word" der SQL-Datenbank ist. Beispielsweise darf ein Feld nicht Primary genannt werden. |
Zugriff auf externe Datenbank via ODBCIm folgenden ein paar Code-Beispiele wie man aus Dynamics AX heraus auf externe Datenbanken lesend und schreibend zugreifen kann. Die Beispiele basieren auf folgendem MSDN-Beitrag: Lesender Zugriff (SELECT)// X++, Main method in a class. static public void Main(Args _args) { LoginProperty loginProperty; OdbcConnection odbcConnection; Statement statement; ResultSet resultSet; str sql, criteria; SqlStatementExecutePermission perm; ; // Set the information on the ODBC. loginProperty = new LoginProperty(); loginProperty.setDSN("ExternalDB_32bit"); loginProperty.setDatabase("ExternalDatabaseName"); //Create a connection to external database. odbcConnection = new OdbcConnection(loginProperty); if (odbcConnection) { sql = "SELECT * FROM items;"; //Assert permission for executing the sql string. perm = new SqlStatementExecutePermission(sql); perm.assert(); //Prepare the sql statement. statement = odbcConnection.createStatement(); resultSet = statement.executeQuery(sql); //Cause the sql statement to run, //then loop through each row in the result. while (resultSet.next()) { //It is not possible to get field 3 and then 1. //Always get fields in numerical order, such as 1 then 2 the 3 etc. print strFmt("%1 - %2", strRTrim(resultSet.getString(1)), strRTrim(resultSet.getString(2))); } //Close the connection. resultSet.close(); statement.close(); } else { error("Failed to log on to the database through ODBC."); } } |
AX 2012: Synchronisationsfehler werden angezeigt, obwohl diese bereits gelöst wurdenVor kurzem hatte ich das Problem, daß beim Synchronisieren der Datenbank im Formular Datenbank synchronisieren Fehler und/oder Warnungen ausgegeben wurden, bei denen ich mir sicher war, daß diese bereits behoben wurden. Eine einfache Lösung dafür ist den Inhalt der Tabelle SqlSyncInfo zu löschen. Die Tabelle selbst findet man im AOT unter System Documentation > Tables > SqlSyncInfo. Übrigens gibt es im AOT auch das Formular SysSqlSync, welches man jederzeit öffnen kann und sich dort das Ergebnis der jeweils letzten Synchronisierung ansehen kann. |
Einen (einfachen) SSRS-Bericht in einer bestimmten Sprache aufrufenAm Beispiel des Berichtes CustTransList (Debitorenkonten > Berichte > Buchungen > Debitor > Buchungen) möchte ich zeigen, wie es möglich ist einen Bericht in einer beliebigen Sprache aufzurufen. Für diesen Bericht gibt es keinerlei Klassen in AX, also habe ich mir folgende Klasse selbst erstellt: class CustTransListController extends SrsReportRunController { }
public static str getReportName(Args _args) { str reportName = ssrsReportStr(CustTransList, Report); return reportName; }
public static void main(Args _args) { CustTransListController controller = new CustTransListController(); controller.parmReportName(CustTransListController::getReportName(_args)); controller.parmArgs(_args); controller.parmReportContract().parmRdlContract().parmLanguageId('en-us'); controller.startOperation(); } Mit dieser Klasse kann der Bericht nun in englischer Sprache aufgerufen werden (bzw. in jener Sprache, die man der Methode parmLanguageId() übergibt). |
|
|
|
|
|
|
Nachstehend ein kurzer Job, mit dessen Hilfe man AOT-Elemente zu einem bestehenden Shared Project hinzufügen kann.
{
projectNode projectNode;
TreeNode treeNode;
#AOT
#AOTExport
projectNode = infolog.projectRootNode();
projectNode = projectNode.AOTfindChild(#expProjectShared);
projectNode = projectNode.AOTfindChild('MyProject');
// Add objects
treenode = TreeNode::findNode(#TablesPath+'\\'+tableid2name(tablenum(CustGroup)));
projectNode.addNode(treenode);
treenode = TreeNode::findNode(#TablesPath+'\\'+tableid2name(tablenum(VendGroup)));
projectNode.addNode(treenode);
treenode = TreeNode::findNode(#ClassesPath+'\\'+classStr(PriceDisc));
projectNode.addNode(treenode);
}
Das geänderte Projekt sieht beispielsweise wie folgt aus: