Beim Entwickeln und/oder Testen von AIF-Service, welche als Webservice bereit gestellt werden, entstehen oftmals (mindestens) 2 Fragestellungen.
- Wie kann die Nachricht betrachtet werden, welche zwischen den System über den Webservice ausgetauscht wird?
- Wie lässt sich der Webservice-Aufruf debuggen?
Leider werden diese Fragen bei einer Suche im Internet oft mit “Geht nicht” beantwortet. Dies ist so allerdings nicht richtig.
Es ist z.B. möglich, für alle Webserviceaufrufe eine Tracing-File zu erzeugen, welches u.A. auch die Nachricht protokolliert, die von oder zu Dynamics AX geschickt wurde. Um das Tracing zu aktivieren müssen nur entsprechende Einstellungen in der web.config des Webservices vorgenommen werden.
Wie dies im Detail funktioniert beschreibt dieses kleine How-To des Microsoft Dynamics Developer Centers im MSDN. http://msdn.microsoft.com/en-us/library/cc967372.aspx
Es ist ebenfalls möglich, die Webserviceaufrufe zu debuggen.
Allerdings müssten hierfür einige Schritte beachtet werden, damit das Debuggen von Webserviceaufrufen auch für X++ Code funktioniert. Eine detaillierte Anleitung hierzu ist am Ende des Whitepapers “Tips for Creating Services in Microsoft Dynamics AX 2009” zu finden. http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=90388b14-fb8c-4633-a255-28ff7146c5b2
Um Datensätze in Microsoft Dynamics AX, welche z.B. auf einer Maske angezeigt werden, entsprechend seiner Anforderungen einzuschränken (zu filtern) muss die Query (Abfrageobjekt) durch Erstellung von Ranges (Abfrageeinschränkungsobjekt) entsprechend “manipuliert” werden. Hierfür wird z.B. die Query einer Maskendatenquell (DataSource) verwendet und für diese eine neue Range definiert:
Beispiel:
public void init() { QueryBuildRange range; ; super(); range = CustTable_ds.query().dataSourceTable(tablenum(CustTable)).addRange(fieldnum(CustTable, AccountNum)); range.value("1101");}
Im Dynamics AX Standard kann ähnlicher X++ Quelltext in vielen Masken gefunden werden, da dies der “Standard-Weg” zum Einschränken von Datensatzabfragen bei Masken oder auch Reports ist. Ebenso wird dieses Vorgehen auch in den Schulungsunterlagen, in der Entwicklerhilfe und anderen Stellen beschrieben.
Leider hat dieses Vorgehen eine kleine aber teilweise sehr störende Beschränkung. Über diesen Weg ist es nicht möglich, alle Abfrageeinschränkungen welche durch X++ Quellcode “gesetzt” wurden und Einschränkungen, welche durch einen Benutzer mittels der Standardfilterfunktion von Dynamics AX definiert wurden, zu berücksichtigen. Beim einer Datenaktualisierung (Aufruf von DataSource.executeQuery) gehen die von einem Benutzer definierten Abfrageeinschränkungen verloren.
Dies ist darin begründet, dass es nicht nur ein DataSoucre.query-Objekt, sondern auch ein DataSource.queryrun().query-Objekt gibt. Diese beiden “Query-Objekte” sind jeweils unterschiedliche Objekte, bzw. Objektinstanzen.
Das DataSource.query-Objekt ist das “Basisabfrageobjekt”, welches durch einen Benutzer, mittels der Filterfunktionalität des Standards, nicht verändert werden kann (nur durch X++ Code). Alle durch den Benutzer vorgenommenen Änderungen an der “Basisabfrage” werden in dem Query-Objekt von DataSource-queryrun() “gespeichert”. Dies kann unter Anderem durch Betrachtung des SQL-Statements, welches durch ein Query-Objekt bereit gestellt wird nachgewiesen werden.
Beispiel:
Aufruf einer Maske mit einer durch X++ Code modifizierten Abfrage (Query). Anmerkung: Beim Aufruf der Maske wird in der “Init-Methode” eine Range (CustGroup = “10”) gesetzt. range = CustTable_ds.query().dataSourceTable(tablenum(CustTable)).addRange(fieldnum(CustTable, CustGroup));
range.value("10");
Durch den Benutzer wird nun mittels der Dynamics AX Standard-Filterfunktion die Abfrage bzw. deren Einschränkung(en) angepasst/verändert.
Hierdurch ist zu beobachten, das sich zwar das SQL-Statement des DataSource.queryrun().query-Objekts, aber nicht das SQL-Statement des DataSoucre.query-Objekts ändert. Da bei einem Aufruf von DataSource.executeQuery allerdings immer das DataSource.query-Objekt verwendet wird, gehen die durch den Benutzer gewählten Abfrageeinschränkungen verloren.
Wie ist es nun aber möglich, die von einem Benutzer gewählten Abfrageeinschränkungen/Filtereinstellung doch zu berücksichtigen?
Da alle Abfrageeinschränkungen, welche von einem Benutzer gewählt wurden, in dem Query-Objekt von DataSource.queryrun() “gespeichert” werden und somit auch im X++ Code zur Verfügung stehen ist dies recht einfach. Es muss einfach das Query-Objekt von DataSource.queryrun() genommen werden, um die gewünschten Ranges ergenzt werden und schließlich dass Query-Objekt der DataSource überschrieben werden.
Beispiel:
Basis ist eine einfach Maske, welche alle Kundendatensätze anzeigt.
Dieser Maske/Abfrage wird nun durch die Standard-Filterfunktion (Benutzerfilter) eine neue Abfrageeinschränkung hinzugefügt (Kundennummer = 1101 und 2001).
Wie zuvor beschrieben, wird nun eine neue Abfrageeinschränkung mit X++ Code auf dem Query-Objekt von DataSource.queryrun “gesetzt” und das Query-Objekt der DataSource mit diesem überschrieben.
void clicked() { Query query; QueryBuildRange range; ; super(); query = CustTable_ds.queryRun().query(); range = query.dataSourceTable(tablenum(CustTable)).addRange(fieldnum(CustTable, CustGroup)); range.value("10"); CustTable_ds.query(query); CustTable_ds.executeQuery(); }
Dies hat zur Folge, dass die durch den Benutzer gewählten Abfrageeinschränkungen, wie zu sehen, weiterhin berücksichtigt werden.
Alternativ zur Verwendung der Abfrageeinschränkung (Range) “direkt” über das Query-Objekt kann auch mit einem oder mehreren Filtern gearbeitet werden. Diese unterliegen im Gegensatz zu den Query-Objekt aber einigen Einschränkungen, sodass diese nicht in jeder Situation verwendet werden können.
Der folgende X++ Code zeigt, wie ein Filter gesetzt werden kann.
void clicked() { Query query; QueryBuildRange range; ; super(); CustTable_ds.filter(fieldnum(CustTable, CustGroup), "10"); }
Wird eine Abfrage auf diese Art und Weise eingeschränkt, ist der Aufruf von DataSource.executeQuery() unnötig, da die Datenaktualisierung bereits im Hintergrund durch den Filter-Aufruf durchgeführt wird. Filter einer DataSource funktionieren vom Prinzip her wie die Standardfilter, welche durch einen Benutzer in Dynamics AX gesetzt werden können. Dies hat zur Folge, dass sich diese ebenfalls nur auf das Query-Objekt von DataSource.queryrun() auswirken und somit DataSource.query nicht beeinflussen.
Mit der Methode DataSource.removeFilter können die gesetzten Filter wieder gelöscht werden. Leider werden hierdurch alle gesetzten Filter gelöscht, sodass nach diesem Aufruf unter Umständen einige bereits gesetzte Filter erneut gesetzt werden müssen, um das gewünschte Abfrageergebnis zu erhalten.
Welche der gezeigten Methoden, zum Einschränken von Abfragen, aber nun der beste oder bessere Weg ist, muss von Fall zu Fall entschieden werden.
Oftmals besteht die Anforderung, über einen Zeitgesteuerten Job (Batchjob), das Generieren von statistischen Berichten, welche in einer Datei gespeichert werden soll, zu automatisieren.
Microsoft Dynamics AX stellt hierfür die Möglichkeit bereit, jeden Bericht mithilfe der Stapelverarbeitung zu einem definierten Zeitpunkt zu generieren und in einer Datei, z.B. in einem Netzwerklaufwerk, bereit zu stellen. Soweit stellt dies kein Problem dar, da über den Standard von Dynamics AX diese Anforderung ohne weiteres erfüllt werden kann.
Leider wird hierbei oft vergessen, dass der entsprechende Batchserver (AOS) so konfiguriert werden muss, dass dieser das “Drucken auf dem Server” zulassen muss. Dies ist eine Einstellungsoption des Serverkonfigurations-Utilities.
Weiterhin sollte bei der Angabe der Datei bzw. des Speicherortes der Datei immer ein UNC-Pfad verwendet werden, da die eigentlich Ausführung des Berichtes und somit auch die Erstellung der Datei über das Benutzerkonto des AOS-Dienstes geschieht.
Dies bedingt auch, dass entsprechende Berechtigungen für das Dienstkonto des Batchservers (AOS) für das freigegebene Verzeichnis vergeben werden müssen, damit die Datei und somit der Bericht erfolgreich erstellt werden kann.
Eine weiterführende Beschreibung hierzu ist auch im EMEA Dynamics AX Support Blog zu finden.
In Microsoft Dynamics AX wird das Args-Objekt dazu verwendet, Informationen z.B. an eine aufzurufende Maske oder Klasse zu übergeben.
Mittels des Args-Objektes ist es z.B. möglich, den auf einer Maske ausgewählten Datensatz an die Aufzurufende (Unter)Maske zu übergeben, um mit diesem die Darstellung und/oder Funktionen der Maske anzupassen. Oft wird dieses Vorgehen dazu verwendet, Abfragen (Queries) entsprechend einzugrenzen, damit nur relevante Informationen verarbeitet werden. Eine beispielhafte Anforderung hierfür könnte sein, alle Aufträge des zuvor ausgewählten Kunden in einer neuen Maske anzuzeigen.
Manchmal ist aber notwendig, nicht nur den Aufrufer (oder den gewählten Datensatz), sondern auch dessen Aufrufer zu kennen, um bestimme Funktionalitäten erstellen oder implementieren zu können. Herbei kann es sein, dass der ausgewählter Datensatz über mehrere Aufrufebenen übergeben werden muss und der direkte Aufrufer dennoch bekannt sein muss.
Nehmen wir an, es existiert eine Hauptmaske, auf der ein Kundendatensatz ausgewählten werden kann. Auf einer weiteren Maske (1. Maske), sollen nun alle Aufträge des ausgewählten Kunden angezeigt werden. Diese Maske soll über die Hauptmaske aufgerufen werden. Über eine 2. Maske, welche über die 1. Maske aufgerufen werden soll, sollen die Adressdaten des Kunden angezeigt werden.
Um nun die benötigten Information, ausgewählter Kunden in der Hauptmaske, auf der 2. Maske zur Verfügung zu haben, muss über das FormRun-Objekt der 1. Maske der Aufrufer (Caller) dieser Maske bestimmt werden.
Beispiel (Init-Methode der 2. Maske):
public void init() { Object callerDataSource; FormRun callerFormRun; common callerRecord; common callerRecordOfCallerRecord; ; super(); if(element.args() && element.args().dataset()) { callerRecord = element.args().record(); callerDataSource = callerRecord.dataSource(); callerFormRun = element.args().caller(); callerRecordOfCallerRecord = callerFormRun.args().record(); CtrlCallerTable.text(tableid2name(callerRecord.TableId)); CtrlCallerOdCallerTable.text(tableid2name(callerRecordOfCallerRecord.TableId)); } }
Sicherlicht läßt sich das in dem Beispiel beschriebene Verhalten auch anders (oder eleganter) Lösen. Dieses Beispiel wurde nur gewählt, um den Ablauf oder die notwendigen Schritte zu demonstrieren, wie Aufrufer über mehrere Ebenen bestimmt werden können.
Notizen, Dokumente oder Dateien werden in Dynamics AX mithilfe des “Dokumentenmanagement-Systems” verwaltet.
Zu jedem beliebigen Datensatz einer beliebigen Tabelle (z.B. CustTable -> Debitoren) können beliebig viele Notizen oder Dokumente hinterlegt werden. Per Benutzeroberfläche kann die entsprechende Funktionalität über die Menüleiste der Masken aufgerufen werden.
Das folgende Beispiel zeigt wie dies auch per Programmcode erfolgen kann:
static void AKU_CreateDocuRefNote(Args _args) { CustTable custTable; DocuRef docuRef; DocuType docuType; ; custTable = CustTable::find("1101"); docuType = DocuType::find("Note"); if(custTable && docuType) { docuRef.initValue(); docuRef.RefTableId = custTable.TableId; docuRef.RefRecId = custTable.RecId; docuRef.RefCompanyId = custTable.dataAreaId; docuRef.TypeId = docuType.TypeId; docuRef.Restriction = DocuRestriction::External; docuRef.Name = "Name der Notiz"; docuRef.Notes = "Text (Inhalt) der Notiz"; docuRef.insert(); } }
Am 23. und 24. November 2009 fand der Dynamics Technical Airlift 2009 im Hotel The Westin Grand München Arabellapark in München statt. Wie auch schon im letzten Jahr, richtete sich die Veranstaltung an die eher technisch ausgerichteten Personen (Consultants/Entwickler) aus der Dynamics-Partner-Gemeinde (Dynamics AX, Dynamics NAV und Dynamics CRM).
|
Ich selbst durfte in diesem Jahr wieder als ATE (Ask the Expert) an dieser Veranstaltung teilnehmen und mich u.a. in einer eigenen Session, zusammen mit den anderen Experten, den Fragen der Teilnehmer “stellen”.
Wie schon in den letzten Jahren, gab es viele produktbezogene “Break-Out-Sessions”, die sich in diesem Jahr erstmals nicht nur mit technischen Themen befassten. Insgesamt denke ich, dass es wieder eine gelungene Veranstaltung war. Sicherlich waren einige Session für den einen oder anderen nicht in der gewünschte technische Tiefe, lieferten aber einen guten "Know-How Refresh". Es ist meist auch schwer, mit einer speziellen Session oder einem speziellen Thema, bei einer solch großen Veranstalltung, immer jeden ansprechen zu können. Ich hatte jedenfalls das Gefühl, dass, gerade für Einsteiger oder “Jung-Professionals”, wirklich gute Themen behandelt wurden.
Durch den gemeinsamen Informationsaustausch, u.a. auch durch den ATE-Stand, und die vielen Gespräche mit Personen aus der Dynamics-Gemeinde wurde die Veranstaltung positiv abgerundet. |
 |
Da Meinungen ja bekanntlich weit auseinander gehen, möchte ich jeden einzelnen bitten, seine Eindrücke und Meinungen zu dem Dynamics Technical Airlift 2009 kurz zu schildern. Besonders die Meinungen über die “Ask-The-Expert Session”, welche am ersten Tag statt fand würden mich interessieren.
Wer dies nicht "öffentlich", z.B. durch die Kommentarfunktion machen möchte, kann mir auch gerne eine Email schreiben (Email me). Bitte beachtet, dass alle Kommentare erst durch mich "überprüft" werden müssen, bevor sie angezeigt werden.
In Microsoft Dynamics AX beziehen Masken ihre Daten, oder anders gesagt die Daten welche sie anzeigen, über so genannte DataSources. In einer DataSource sind somit die aktuellen auf der Maske angezeigten Daten (lokal) gespeichert.
Zugriff auf den jeweils aktuell ausgewählten Datensatz erhält man üblicherweise über genau diese DataSource. Der ausgewählte Datensatz kann unter anderem auch, z.B. durch ein MenuItem(Button), an eine Funktion oder andere Maske übergeben werden. Hierfür muss nur die Eigenschaft “DataSource”, in diesem Beispiel des MenuItem(Button), entsprechend eingestellt sein.
Ist keine DataSource in den Eigenschaften hinterlegt wird immer die erste DataSource der Query verwendet bzw. dessen aktiver Datensatz übergeben. In der Regel ist dies die DataSource, welche beim Erstellen der Maske als erstes hinzugefügt oder erstellt wurde (Ausnahme ist hier eine eventuelle Manipulation der Query per Programmcode).
Dieses Vorgehen ist für 90% aller Fälle das wohl am besten geeignete Vorgehen und wird in dieser Weise auch vom Dynamics AX Standard verwendet. Leider gibt es Anwendungsfälle, bei denen diese “starre Verbindung” von DataSource und z.B. Button oder MenuItem nicht funktioniert, beziehungsweise nicht zum gewünschten Ergebnis führt.
Angenommen man hat eine Maske mit zwei DataSources (CustTable und SalesTable), deren Daten über zwei Grids angezeigt werden, sowie einen Button, welcher eine Operation mit dem zuletzt ausgewählten Datensatz (unabhängig von der DataSource) durchführen soll. Wenn ein Datensatz der DataSource “CustTable” selektiert wurde, soll dieser verarbeitet werden. Ist zuletzt ein Datensatz der DataSource “SalesTable” selektiert wurden, soll die Operation mit diesem Datensatz erfolgen.
Bei dieser Anforderung ergibt sich das Problem, dass die Standardvorgehensweise zur Abfrage des selektierten Datensatzes nicht funktioniert, da hierfür eine der DataSources “direkt” angesprochen werden muss. Welche DataSource nun aber die “aktive” ist, lässt sich leider nicht ermitteln, da standardmäßig jede DataSource einen “aktiven” Datensatz hat und somit eine Unterscheidung, ob der Aufruf für die “CustTable” oder “SalesTable” erfolgen soll, nicht möglich ist.
Über die Methode “docCursor” der Klasse FormRun bietet sich eine zweite Möglichkeit, den aktiven (ausgewählten) Datensatz zu ermitteln. Dieses Vorgehen wird z.B. vom Dokumentenmangement (Form “DocuView”) verwendet, um den zuletzt gewählten Datensatz zu ermitteln und somit die dem Datensatz zugeordneten Dokumente anzuzeigen.
Leider scheidet dieser Weg ebenfalls aus, da ein “Click” auf den Button zur Folge hat, dass der jeweils aktive Datensatz der “Button-DataSource” durch die Methode “docCursor” zurück geben wird. Dies ist soweit auch logisch, da ein Button immer einer DataSource zugeordnet ist (entweder über Angabe in der entsprechenden Eigenschaft des Buttons oder, wenn nicht festgelegt, die erste DataSource der Query).
Wie ist es nun aber möglich, dennoch den zuletzt selektierten (ausgewählten) Datensatz zu ermitteln, wenn die im Standard verwendeten Wege nicht funktionieren?
Um das gewünschte Ziel zu erfüllen (bestimmen, welcher der zuletzt selektierte Datensatz ist) muss eine kleine funktionale Erweiterung der “Info” Klasse durchgeführt werden.
Zuerst müssen in der “classDeclaration” der Klasse “Info” zwei neue Variablen/Buffer zum Speichern des selektierten Datensatzes erstellt werden.
final class Info extends xInfo { #SysTaskRecorderMacro ObjectIdent docuView; ObjectIdent lastActivatedForm; ... // New code --> Common lastSelectedRecord; Common selectedRecord; //New code <-- #Define.CurrentVersion(1) }
Nun müssen noch einige neue Methoden für die Klasse “Info” erstellt werden, damit die Variablen/Buffer geschrieben, abgefragt und gelöscht werden können.
private void setLastSelectedRecord(FormRun _formRun) { ; if(_formRun.docCursor()) { if(lastSelectedRecord) { lastSelectedRecord = selectedRecord; } else { //Only get the record data, not the cursor lastSelectedRecord = _formRun.docCursor().data(); } //Only get the record data, not the cursor selectedRecord = _formRun.docCursor().data(); } }
private void clearLastSelectedRecord() { ; lastSelectedRecord.clear(); selectedRecord.clear(); }
common lastSelectedRecord() { ; return lastSelectedRecord; }
Zum Schluss müssen diese neu erstellten Methoden noch entsprechend in der Methode “formNotify” aufgerufen werden.
void formNotify(FormRun formRun,FormNotify event) { switch (event) { case FormNotify::Activate: this.activate(formRun); if (docu) docu.reSearch(formRun); //New code --> this.setLastSelectedRecord(formRun); //New code <-- break; case FormNotify::DeActivate: break; case FormNotify::Open: this.open(formRun); if (docu) docu.set(formRun); break; case FormNotify::Close: this.close(formRun); if (docu) docu.clear(formRun); //New code --> this.clearLastSelectedRecord(); //New code <-- break; case FormNotify::RecordChange: if (docu) docu.reSearch(formRun); //New code --> this.setLastSelectedRecord(formRun); //New code <-- if (formRun.isWorkflowEnabled()) { // only refresh controls if current ds equals workflow data source if (formRun.objectSet().name() == formRun.workflowDataSource().name()) formRun.updateWorkflowControls(); } break; case FormNotify::NoteClicked: if (docu) docu.note(formRun); break; } }
Durch diese kleine Codeänderung kann nun der zuletzt ausgewählte Datensatz, unabhängig von einer DataSource, abgefragt werden.
void clicked() { Common currentRecord; DictTable dictTable; ; super(); //Get the last selected record currentRecord = infolog.lastSelectedRecord(); dictTable = new DictTable(currentRecord.TableId); setPrefix(tableid2name(currentRecord.TableId)); info(strfmt("%1 - %2", currentRecord.(dictTable.titleField1()), currentRecord.(dictTable.titleField2())));} Bezogen auf die zuvor beschrieben Anforderung könnte das Ergebnis so aussehen.

In Microsoft Dynamics AX existiert ein Feature, um Aufgaben (Jobs), welche durch entsprechende Klassen bereit gestellt werden, zu planen und zu einem geplanten Zeitpunkt auszuführen. Dies wird in Dynamics AX als Stapelverarbeitung (Batch-Framework) bezeichnet.
Jeder Stapelverarbeitungsauftrag verfügt über einen Status, der angibt, in welchem “Zustand” sich der jeweilige Stapelverarbeitungsauftrag befindet.
Über die Funktion, “Funktionen –> Status ändern” kann dieser Status durch den Benutzer geändert werden.
Beim Auswählen des “neuen” Status ist leider ein wenig Vorsicht geboten, da bei einem falschen Klick der gesamte Stapelverarbeitungsauftrag unbrauchbar gemacht werden kann. Drückt man zufällig nicht auf einen der durch die Maske angebotenen Werte, so wird der Status der Stapelverarbeitungsauftrags gelöscht.
Das unschöne hierbei ist, dass dieses “Status löschen “nicht mehr rückgängig gemacht werden kann (jedenfalls nicht durch die Dynamics AX Masken). Bei dem Versuch, wieder einen korrekten Status zu vergeben (ebenfalls über die Funktion “Status ändern”) wird leider nicht der gewünschte Status gesetzt, sondern eine Fehlermeldung ausgegeben.
Die einzige Möglichkeit, wieder eine korrekten Status zu setzten, besteht leider darin, einen kleinen Job zu schreiben (mit X++), welcher den Status per Programmcode ändert.
Ist gerade kein Entwickler “zur Hand”, besteht nur die Möglichkeit, den Stapelverarbeitungsauftrag zu löschen und erneut anzulegen (dies kann aber von Fall zu Fall sehr aufwändig sein).
In mehreren Artikeln wurde bereits beschrieben, wie LookupForms erstellt werden müssen, um alle Funktionen bereit zu stellen, die auch durch einen Standard-Lookup bereit gestellt werden.
Ein guter Artikel ist zum Beispiel auf Axaptapedia zu finden: http://axaptapedia.com/Lookup_Form
Leider wurde in diesem Artikel auf eine Kleinigkeit nicht hingewiesen, die allerdings für sehr viel Verwirrung sorgen kann.
Um beim Öffnen des Lookups den bereits eingetragenen Wert zu selektieren (in dem Control der aufrufenden Maske), müssen wie in dem Artikel beschrieben, die Methoden „executeQuery“ und „init“ der DataSource der Lookup-Maske überschrieben werden.
Beispiel:
public void executeQuery()
{
FormStringControl callerControl = SysTableLookup::getCallerStringControl(element.args());
;
super();
xyz_ds.findValue(fieldnum(xyz,id),callerControl.text());
}
public void init()
{
Query q = new Query();
QueryBuildDataSource qbds;
;
super();
qbds = q.addDataSource(tablenum(xyz));
qbds.orderMode(OrderMode::OrderBy);
qbds.addSortField(fieldNum(xyz,some_other_field));
this.query(q);
}
Es wird auch beschrieben, dass in der Methode “init” der Datasource eigene Ranges oder Sortings definiert werden können. Dies ist soweit auch richtig, allerdings mit einer Ausnahme.
Wird auf dem Feld, welches bei dem Aufruf von „Datasource.findValue“ in der Methode „init“ angegeben wurde (sollte auch immer das Feld sein, dessen Wert durch den Lookup ausgewählt wird), eine Range definiert, so funktioniert die Selektion des zuvor gewählten Wertes nicht mehr und es wird immer der erste Wert im Lookup selektiert bzw. ausgewählt.
Beispiel:
public void executeQuery()
{
FormStringControl callerControl = SysTableLookup::getCallerStringControl(element.args());
;
super();
xyz_ds.findValue(fieldnum(xyz,id),callerControl.text());
}
public void init()
{
Query q = new Query();
QueryBuildDataSource qbds;
QueryBuildRange range;
;
super();
qbds = q.addDataSource(tablenum(xyz));
qbds.orderMode(OrderMode::OrderBy);
qbds.addSortField(fieldNum(xyz,some_other_field));
range = qbds.addRange(fieldnum(xyz,id));
range.value(SysQuery::valueNot(<someValue>));
this.query(q);
}
Dieses Verhalten lässt sich allerdings umgehen, wenn anstelle des Aufrufs von “DataSource.findValue” in der „ExecuteQuery“ Methode der DataSource der Aufruf von „DataSoucre.findRecord“ verwendet wird. Hierfür muss aber der entsprechende Datensatz des zuvor oder bereits ausgewählten Wertes ermittelt werden um diesen beim Aufruf von „DataSource.findRecord“ als Parameter zu übergeben.
Beispiel: public void executeQuery()
{
FormStringControl callerControl;
Xyz xyzRecord;
;
callerControl = SysTableLookup::getCallerStringControl(element.args());
xyzRecord = Xyz::find(callerControl.text());
super();
xyz_ds.findRecord(xyzRecord);
}
public void init()
{
Query q = new Query();
QueryBuildDataSource qbds;
QueryBuildRange range;
;
super();
qbds = q.addDataSource(tablenum(xyz));
qbds.orderMode(OrderMode::OrderBy);
qbds.addSortField(fieldNum(xyz,some_other_field));
range = qbds.addRange(fieldnum(xyz,id));
range.value(SysQuery::valueNot(<someValue>));
this.query(q);
}
Es muss also darauf geachtet werden, ob eine Einschränkung (Range) auf dem „ID-Feld“ benötigt wird oder nicht.
Wird keine Einschränkung benötigt, kann, wie in dem Artikel auf Axaptapedia beschrieben, mit „DataSource.findValue“ gearbeitet werden um den entsprechenden Datensatz zu selektieren. Wird aber eine solche Einschränkung benötigt, muss mit „DataSoucre.findRecord“ gearbeitet werden.
Wird Microsoft Dynamics AX 2009 mit Windows Server 2008 und SQL Server 2008 installiert, kann es zu einem Problem bei Bereitstellen der ODC-Dateien kommen.
Nach dem Aufruf der Funktion „ODC-Dateien bereitstellen“ meldet Dynamics AX 2009 einen Fehler im Infolog.
Diese Fehlermeldung wird ebenfalls im Ereignislog von Windows protokolliert.
Laut einem Artikel im EMEA Dynamics AX Support Blog ist hierfür ein Hot Fix erhältlich. https://blogs.msdn.com/emeadaxsupport/archive/2009/04/23/unable-to-deploy-odc-files-to-enterprise-portal-even-after-installing-hotfix-kb960158.aspx
Wurde allerdings schon das Hot Fix Rollup 2 für Dynamics AX 2009 (SP1) installiert, wird das beschriebene Hot Fix nicht mehr benötigt.
Um nun die ODC-Dateien erfolgreich bereitstellen zu können muss wie folgt vorgegangen werden:
- Das bereits installierte Enterprise-Portal muss aktualisiert werden
(Verwaltung/Einstellungen/Internet/Enterprise Portal/Bereitstellungen verwalten/ Button „Aktualisieren“ wählen)
- Nun (sicherheitshalber) den IIS neu starten, z.B. durch Aufruf von „iisreset“
- Anschließend können die ODC-Dateien bereit gestellt werden.
(Verwaltung/Einstellungen/Unternehmensanalyse/OLAP/Olap-Verwaltung/ Button „ODC-Dateien bereitstellen“ wählen)
Ob das Bereitstellen der ODC-Dateien funktioniert hat, kann überprüft werden, indem man kontrolliert, ob die entsprechende Bibliothek im SharePoint die ODC Dateien enthält. http://<servername>/websites/DynamicsAx/Data%20Connections/Forms/AllItems.aspx
Ab sofort führt mein Arbeitgeber, die Firma AX Solutions GmbH, einmal in der Woche (mittwochs 15:30 - 16:30 Uhr) eine kostenlose „Experten-Sprechstunde“ durch.
Diese „Sprechstunde“ richtet sich an Microsoft Dynamics AX Bestandskunden sowie Interessenten die Antworten auf bisher unbeantwortete Fragen oder einen Rat zu einer speziellen Problemstellung suchen.
Unter anderem werde auch ich diese Sprechstunden abhalten und versuchen nach besten Wissen und Gewissen Rat zu geben. Sicherlich wird sich nicht jede Problemstellung Ad-hoc lösen lassen. Ich bin aber sicher, dass der gemeinsame Dialog zumindest Lösungsoptionen aufzeigen wird.
Guter Rat ist Sprichwörtlich teuer. Diesmal aber nicht, denn die Dynamics AX Sprechstunde ist kostenlos. Auf die sonst übliche Praxisgebühr in Höhe von 10,- EUR pro Quartal wird verzichtet. 
Da die Sprechstunden in einem 1:1 Gespräch durchgeführt werden, und möglichst vielen Ratsuchenden die Möglichkeit gegeben werden soll diese zu nutzen, ist jede Sprechstunde auf 60 Minuten begrenzt.
Ratsuchende bzw. Interessierte möchte ich bitte, sich unter folgendem Link: (http://www.ax-solutions.de/kontaktformular.html) mit dem Stichwort „Dynamics AX – Sprechstunde“ anzumelden.
Weitere Informationen können über die Webseite der AX Solutions GmbH bezogen werden.
Wie schon die erste Auflage des Buches „Inside Dynamics AX“ ist dieses Buch eine sehr gute Ergänzung zu den von Microsoft angebotenen Schulungsunterlagen (Development 1-4).
Angefangen bei der Architektur, der Entwicklungsumgebung und –Tools, bis hin zu Code Upgrades beschreibt dieses Buch alle Themen die für einen AX Entwickler von Bedeutung sind.
Nicht nur alle neuen Features von Dynamics AX 2009, z.B. Dynamics AX Reporting Services oder Workflows, sondern auch ältere Features wie z.B. das Application Integration Framework (AIF), werden wesentlich detaillierter beschrieben als an anderen Stellen.
Leider gibt es auch Bereiche, die nicht so detailliert besprochen werden bzw. wo einige Fragen nicht gänzlich beantwortet werden. Ein Beispiel hierfür ist die .NET Integration. Zwar wird der Business Connector ausreichend beschrieben, aber das Thema CLR-Interoperability wird leider nur sehr knapp behandelt.
Einige Kapitel wurden im Vergleich zu der ersten Auflage des Buches gänzlich überarbeitet. Beispielhaft sei das Kapitel über Form Customizations genannt, welches komplett neu geschrieben wurde.
Leider hat dies auch zur Folge, dass einige sehr gut Beschriebene Themen, wie Beispielweise das dynamische Anpassungen von Masken mit X++, jetzt nicht mehr behandelt werden.
Was dieses Buch aber nicht beschreibt oder behandelt, sind die Klassen, Tabellen, API‘s, etc. des Microsoft Dynamics AX Standards. Dies würde allerdings auch den Rahmen des Buches mehr als sprengen.
In der Gesamtbetrachtung ist die neue Auflage von Inside Microsoft Dynamics AX eins der besten technischen Bücher über Microsoft Dynamics AX. Kein Buch geht soweit in die Tiefe wie dieses. Egal ob Anfänger oder erfahrener Entwickler, für jeden ist etwas dabei.
Auch wer schon die erste Auflage von Inside Microsoft Dynamics AX gelesen hat, wird viele neue Themen finden.
Die neue oder zweite Auflage von "Inside Mircosoft Dynamics AX" ist vor wenigen Tage erschienen.
Inside Mircosoft Dynamics AX 2009
Wie auch schon die erste Auflage des Buches, welche auf der Version 4.0 von Microsoft Dynamics AX basierte, ist diese Buch in erster Linie für Entwickler gedacht. Die aktuelle Auflage umfasst gut 100 Seiten mehr als die erste Auflage und ist leider auch im Preis etwas teurer.
Weitere Informationen über den Inhalt können z.B. auf den Seiten von Amazon entnommen werden.
Es ist zu hoffen, dass sich diese Auflage auf gleichem Level wie die erste Auflage bewegt und somit zu einem "Must-Have" oder "Must-Read" für AX Entwickler wird.
Heute bin ich, bei einem meiner "Streifzüge" durch das Internet, auf eine neue Seite zum Thema Dynamics gestoßen.
Diese neue Seite heißt DynamicsWorld.
Als einer der ersten Einträge, wurde dort eine Liste der 100 einflussreichsten Menschen, bezogen auf Microsoft Dynamics, veröffentlicht. Wie diese Liste erstellt wurde, bzw. welche Kriterien zur Erstellung dieser Liste verwendet/berücksichtigt wurde ist ebenfalls beschrieben.
Nach einem Blick auf diese Liste war ich sehr erstaunt. Unter Position 62 ist folgendes zu lesen (Orginalauszug):
Axel Kühn
One of the German Dynamics AX developers who has resisted the temptation to fall in to the arms of SAP. He has been a regular contributor to the GLS layer for Germany and is involved in some of the largest AX implementations, his blog blog.ak-home.net regularly has a readership of over 3000 AX developers and consultants.
Der orginale Eintrag ist hier zu finden.
Ich freue mich zu lesen, dass meine Bemühungen und Beiträge zu der Microsoft Dynamics Community so hoch bewertet werden.
In dem Artikel "Anzeige von Lagerdimensionen auf Masken" wurde bereits gezeigt, was zu tun ist, um die Anzeige von Lagerdimensionen auf Masken dynamisch anpassen zu können bzw. das Standardverhalten für die Anzeige von Lagerdimensionen zu implementieren.
Manchmal soll eine ähnliche Funktionalität auch für Berichte bereit gestellt werden, um zum Beispiel vor der Berichtserstellung auswählen zu können, welche Lagerdimensionen auf dem Bericht(Report) angedruckt werden. Auch hierfür sind im Dynamics AX Standard die entsprechenden Funktionalitäten (oder besser Klassen) bereits vorhanden, sodass diese nur verwendet werden müssen.
Als Ausgangsbasis für den Bericht dient ebenfalls die Tabelle „AKU_DemoTable“.

Der Bericht soll nun, die in dieser Tabelle gespeicherten Datensätze andrucken/ausgeben.

Wie bei Masken, muss auch für einen Bericht, die Query entsprechend um die Tabelle InventDim ergänzt werden. Hierbei ist zu beachten, dass die Eigenschaften (Properties) „FetchMode“ auf „1:1“ und „Relations“ auf „Yes“ gesetzt werden.

Als nächstes muss nun, ebenfalls analog zu dem Vorgehen bei Masken, die Feldgruppe „InventoryDimensions“ in den Designzweig des Reports aufgenommen werden. Beispielhaft wird diese in einem Body-Element erstellt.

Nun müssen noch einige Anpassungen an den Methoden des Berichts durchgeführt werden, damit das gewünschte Ergebnis erreicht werden kann. Bezogen auf die Möglichkeit, die zu druckenden Lagerdimensionen bestimmen zu können, müssen die Methoden „classDeclaration“, „run“, „dialog“ und „getFromDialog“ wie folgt überschrieben werden. Auch das Überschreiben der Methoden „pack“ und „unpack“ ist hilfreich (für die Lagerdimensionsanzeige nicht zwingend erforderlich), da über diese die Speicherung der „Nutzungsdaten“ realisiert wird.
public class ReportRun extends ObjectRun { InventDimParm inventDimParm; DialogRunbase dialog; DialogGroup dialogInventoryDimensions;
#define.CurrentVersion(1) #localmacro.CurrentList inventDimParm #endmacro }
void updateDesign() { ; InventDimCtrl::updateReportVisible(element, inventDimParm); }
public void run() { ; this.updateDesign(); super(); }
public Object dialog(Object _dialog) { ; dialog = _dialog; dialogInventoryDimensions = inventDimParm.addFieldsToDialog(dialog,"@SYS53654",true, false, "@SYS102592"); return dialog; }
public boolean getFromDialog() { ; inventDimParm.getFromDialog(dialog, dialogInventoryDimensions); return true; }
public container pack() { return [#CurrentVersion, #CurrentList]; }
public boolean unpack(container packedClass) { Version version = RunBase::getVersion(packedClass); ; switch(version) { case #CurrentVersion: [version,#CurrentList] = packedClass; break; default: return false; } return true; }
Wird nun der Bericht geöffnet, zum Beispiel über ein MenuItem, kann in einem Dialog ausgewählt werden, welche Lagerdimensionen auf dem Report angedruckt werden sollen.

Der ausgegebene Bericht(Report) sieht, unter Berücksichtigung der im Dialog gewählten Einstellungen, wie folgt aus.

Das vorgestellt Bespiel steht hier als Download bereit um die einzelnen Schritte genau ansehen/nachvollziehen zu können.
AKU_Demo_InventDimRep.rar (1,99 KB)
Im Standard von Microsoft Dynamics AX besteht auf jeder Maske, auf der Artikel und deren Lagerdimensionen angezeigt werden, die Möglichkeit, die Lagerdimensionen, bzw. die angezeigten Felder der Lagerdimensionen, über die Funktion "Lager-Dimensionenanzeige" entsprechend zu steuern.
Die einzelnen Elemente (Felder) der Lagerdimension können über diese Funktion ein- bzw. ausgebledet werden.
Weiterhin ist es auch möglich, durch Parametrisierung zu bestimmen, ob ein Feld einer Lagerdimension eingeben werden muss (Mussfeld) oder ob überhaupt eine Eingabe möglich ist.
Ein gutes Beispiel hierfür ist die Maske "Aufträge".
Wie ist es nun, wenn eine neue Maske erstellt werden soll, welche Artikelinformation und Lagerdimensionen anzeigen soll? Wie genau muss vorgegangen werden, um die bereits an vielen Stellen im Standard verwendete Funktionalität auch für die selbst erstellte Maske bereitzustellen?
Gehen wir einmal davon aus, es wurde eine neue Tabelle erstellt, welche die Artikelnummer (ItemId) und die Lagerdimensionsnummer (InventDimId) speichert. Für diese Tabelle soll eine Maske erstellt werden, úm dem Benutzer die Möglichkeit zu geben, Datensätze zu erfassen, zu ändern oder einfach nur anzuzeigen.
Dies könnte z.B. so aussehen:

Um nun die Funktion der Lagerdimensionensteuerung einzubauen muss zuerst die Tabelle InventDim als DataSource der Maske hinzugefügt werden. Anschließend müssen die Eigenschaften (Properties) der DataSource noch auf folgende Werte geändert werden.
|
Name |
InventDim |
|
JoinSource |
Haupt-Datenquelle (hier: AKUDemoTable) |
|
LinkType |
InnerJoin |
|
DelayActive |
No |
|
InsertAtEnd |
No |
|
InsertIfEmpty |
No |

Nun muss eine neue ButtonGroup (Name: "Inventory") im Designzweig der Maske erstellt werden. Diese sollte das LAbel "Lager" zugewiesen werden. Nun noch das MenuItem "InventDimParmFixed" in diese ButtonGroup ziehen (z.B. per drag & drop aus dem AOT) und dem so erstellten MenuItemButton folgende Eigenschaften zuweisen.
|
Name |
InventDimParmFixed |
|
MenuItemName |
InventDimParmFixed |
|
DataSource |
Haupt-Datenquelle (hier: AKUDemoTable) |

Über das MenuItem (oder genauer über den erstellten MenuItemButton) wird nun wie im Standard, die Maske "Lagerdimensionen" zu öffnen.

Allerdings öffnet sich die Maske „Lagerdimensionen“ noch nicht wie gewünscht über den MenuItemButton. Hierfür sind noch weitere Anpassungen notwendig.
Damit sich die Maske „Lagerdimensionen“ wie gewünscht öffnet muss die neue Maske die Methode „inventDimSetupObject“ implementieren welche eine Instanz von „InventDimCtrl_Frm“ zurück gibt.
Die Klasse „InventDimCtrl_Frm“, bzw. eine der von ihr abgeleiteten Klassen, steuert z.B. welche Lagerdimensionen für den aktuellen Datensatz zulässig sind oder welche Dimensionen für den aktuellen Datensatz angegeben werden müssen, damit dieser gespeichert werden kann.
Da über die Parametrisierung der Lagersteuerungsgruppen und der Modulparameter hierfür durchaus unterschiedliche Einstellungen gewählt werden können, sind in Dynamics AX etliche Ableitungen dieser Klasse vorhanden (jede wird für eine oder mehrere andere Masken verwendet).

Je nachdem, was für eine Funktionalität bzw. was für ein Business-Prozess erstellt werden soll, kann entweder eine der bereits im Standard vorhandenen Klassen verwendet werden oder es muss eine neue Klasse geschrieben werden, um die benötigte Funktionalität zu liefern (z.B. welche Dimensionen immer angezeigt werden müssen).
Das Erstellen einer neuen Klasse, welche von „InventDimCtrl_Frm“ abgeleitet ist, ist recht einfach.
Es sollte immer die Methode „new“ überschrieben werden und mindestens die statischen Methoden „construct“ und „newFromForm“ erstellt werden.
class AKUInventDimCtrl_Frm_Demo extends InventDimCtrl_Frm { }
protected void new() { super(); }
public static AKUInventDimCtrl_Frm_Demo construct() { return new AKUInventDimCtrl_Frm_Demo(); }
static AKUInventDimCtrl_Frm_Demo newFromForm(FormRun _formRun) { AKUInventDimCtrl_Frm_Demo inventDimCtrl = AKUInventDimCtrl_Frm_Demo::construct(); InventDimAxFormAdapter adapter = InventDimAxFormAdapter::newFromForm(_formRun); ; inventDimCtrl.parmCallingElement(adapter); inventDimCtrl.init(); return inventDimCtrl; }
Weiterhin können noch andere Methoden überschrieben werden, um z.B. zu steuern, welche Felder der Tabelle „InventDim“ beim Aufruf der Maske angezeigt werden sollen. Weitere Informationen hierzu sind im Microsoft Dynamics AX Developer Center zu finden: http://msdn.microsoft.com/en-us/library/cc618009.aspx
NoYes mustShowGridField(fieldId _dimFieldId) { NoYes ret;
ret = super(_dimFieldId); //always show InventLocationId in Grid if(_dimfieldId == fieldnum(InventDim, InventLocationId)) { ret = NoYes::Yes; }
return ret; }
Wie zuvor beschrieben muss nun die Methode „inventDimSetupObject“ auf der Maske implementiert werden. Das diese eine Instanz von „InventDimCtrl_Frm“ zurück geben muss, ist diese ebenfalls zu erzeugen. Als erstes muss eine Objektvariable für das „InventDimCtrl_Frm“ Objekt erstellt werden.
public class FormRun extends ObjectRun { InventDimCtrl_Frm inventDimFormSetup; }
Anschließend kann die Methode „inventDimSetupObject“ erstellt werden.
Object inventDimSetupObject() { return inventDimFormSetup; }
Da die Objektvariable durch diesen Quelltext noch nicht initialisiert wird, muss noch entsprechender Code zur Initialisierung geschrieben werden.
void updateDesign(InventDimFormDesignUpdate mode) { inventDimParm inventDimParmShow; inventDimParm inventDimParmEnabled; ; switch (mode) { case InventDimFormDesignUpdate::Init : if (!inventDimFormSetup) { inventDimFormSetup = AKUInventDimCtrl_Frm_Demo::newFromForm(element); } inventDimFormSetup.parmSkipOnHandLookUp(true);
case InventDimFormDesignUpdate::Active : inventDimFormSetup.formActiveSetup( inventTable::find(AKUDemoTable.ItemId).dimGroupId); inventDimFormSetup.formSetControls(true); break;
case InventDimFormDesignUpdate::FieldChange : inventDimFormSetup.formActiveSetup( inventTable::find(AKUDemoTable.ItemId).dimGroupId); inventDim.clearNotSelectedDim(inventDimFormSetup.parmDimParmEnabled()); inventDimFormSetup.formSetControls(true); break;
default : throw error(strfmt("@SYS54195",funcname())); } }
public void init() { ; super(); element.updateDesign(InventDimFormDesignUpdate::Init); }
Da die Logik, welche durch die Methode „updateDesign“ bereit gestellt wird, mehrfach benötigt wird, erfolgt die Initialisierung des „InventDimCtrl_Frm“ Objekts nicht direkt in der „init“ Methode.
Damit die in der Maske erstellten Datensätze auch richtig gespeichert werden können, müssen nun noch einige weitere Anpassungen an den Methoden der Datenquellen vorgenommen werden.
Datasource „AKUDemoTable“ (Hauptdatenquelle): Hier sind die Methoden „write“, „validateWrite“ und „active“ zu überschreiben.
public void write() { ; ttsbegin;
AKUDemoTable.inventDimId = InventDim::findOrCreate(InventDim).inventDimId;
super();
if(AKUDemoTable.inventDimId != InventDim.inventDimId) { InventDim.data(InventDim::find(AKUDemoTable.inventDimId)); InventDim_ds.setCurrent(); }
ttscommit; }
public boolean validateWrite() { boolean ret; ; AKUDemoTable.InventDimId = inventDim::findOrCreate(InventDim).inventDimId;
ret = super(); return ret; }
int active() { int ret; ; ret = super();
element.updateDesign(InventDimFormDesignUpdate::Active);
inventDim_DS.active();
return ret; }
Datasource „InventDim“: Hier müssen die Methoden „initValue“ und „write“ überschrieben werden.
public void initValue() { ; InventDim.data(InventDim::find(AKUDemoTable.inventDimId));
super(); }
public void write() { //super(); }
Hierbei muss unbedingt beachtet werden, dass der „super“ Aufruf in der „write“ Methode der Datasource „InventDim“ auskommentiert wird, um das Speichern von falschen InventDim Datensätzen zu verhindern.
Als letzte Methode sollte nun noch die Methode „modified“ des DataSource-Field „ItemId“ der Datasource „AKUDemoTable“ überschrieben werden, damit auf eine Änderung der Artikelnummer reagiert werden kann (z.B. Artikelabhängige Anzeige der Lagerdimensionen).
public void modified() { ; super(); element.updateDesign(InventDimFormDesignUpdate::FieldChange); }
Somit sind alle benötigten Quelltextanpassungen durchgeführt, sodass nur noch die Feldgruppe „InventoryDimensions“ der DataSource „InventDim“ mit in das Grid gezogen werden muss um die Lagerdimensionen auf der Maske anzuzeigen. Optional kann diese auch in die TabPage „Dimensions“ gezogen werden um ein standardkonformes Aussehen der Maske zu erhalten.

Das vorgestellt Bespiel steht hier als Download bereit um die einzelnen Schritte genau ansehen/nachvollziehen zu können. AKU_Demo_InventDimFrm.rar (2,71 KB)
Leider scheint es ein Problem mit duplizierten Tabellen in Dynamics AX 2009 zu geben. Unter gewissen "Umständen" ist es möglich, Quelltext der in einem andern Layer (z.B. CUS oder BUS) geschrieben wurde, in den SYS Layer zu "verschieben".
Dieser Verhalten ist sehr unschön, da viele Entwickler, z.B. für Testzwecke, mal ein Objekt duplizieren, neuen Quelltext testen und anschließen diesen auf das orginale Objekt übernehmen oder verschieben. Leider taucht genau an dieser Stelle das Problem auf (es kann sein, dass dieses "Verschieben" den Quelltext in den SYS Layer schreibt).
Das genaue Verhalten ist in einem Video von "elranu" auf YouTube beschrieben (Link zum Video):
In den Newsgroups ist auch ein entsprechender Thread zu finden: Ax 2009 bug in Sys Layer
Wie in einem Artikel auf der Microsoft Dynamics AX Webseite zu lesen ist wird der "alte" COM Business Connector nicht mehr in zukünftigen Versionen von Dynamics AX enthalten sein. The COM Business Connector will be discontinued in future releases of Microsoft Dynamics AX
Bereits in der Version 2009 von Microsoft Dynamics AX wird der COM Business Connector vom "normalen" Setup nicht mehr angeboten. Dieser muss manuell, wie im Microsoft Dynamics AX Developer Center beschrieben, nachinstalliert werden. How to: Install COM Business Connector using Command-line Options
Somit ist es an der Zeit, bestehende Lösungen welche den COM Business Connector verwenden, auf den neueren .NET Business Connector zu portieren, um diese Lösungen auch in zukünftigen Versionen verwenden zu können.
Alle benötigten Informationen über die Verwendung des .NET Business Connectors können in der Library des Microsoft Dynamics AX Developer Centers gefunden werden .NET Business Connector Overview
Oft ist in Newsgroups und Foren die Frage zu lesen, wie .NET (CLR) Arrays in X++ verwendet, bzw. wie diese deklariert werden können. Im Großen und Ganzen unterscheidet sich die Syntax für die Verwendung eines .NET Array kaum von der eines reinen X++ Array. .NET Arrays können in X++ sogar auf zwei verschiedene Arten deklariert werden.
Variante 1:
Die Deklaration eines .NET Arrays erfolgt analog zu der Deklaration eines "reinen" X++ Arrays:
System.Object[] arrayOfObjects; System.Int32[] arrayOfIntegers;
Die Syntax für die Instanzierung des .NET Array weicht allerdings leicht von der "normalen" X++ Syntax ab:
arrayOfObjects = new System.Object[10](); arrayOfIntegers = new System.Int32[3]();
Wichtig ist hierbei, dass immer "()" verwendet wird.
Um die Werte eines .NET Arrays zu setzen wird die Methode "SetValue()" verwendet:
arrayOfObjects.SetValue(myObject, 0); arrayOfIntegers.SetValue(300, 1);
Um Werte aus einem Array abzufragen kann die Methode "GetValue" verwendet werden:
arrayOfObjects.GetValue(0); arrayOfIntegers.GetValue(1);
Eine weitere sehr nützliche Methode ist die Methode "get_Length()". Diese liefert die Anzahl der Array-Elemente zurück.
Variante 2:
Alternativ zur ersten Variante besteht noch die Möglichkeit, ein .NET Array über die Klasse System.Array zu erzeugen. Leider stößt man bei diesem Weg immer mal wieder auf kleinere Probleme, weswegen die erste Variante für die Verwendung von .NET Array bevorzugt werden sollte.
Eine etwas ausführlichere Beschreibung der Verwendung von .NET Array in X++ bzw. deren besonderheiten und Abweichungen zur "normalen" X++ Syntax kann im Microsoft Dynamics AX Developer Center gefunden werden.
How to: Use X++ Syntax for CLR Arrays
Das Application Integration Framework von Dynamics AX basiert auf Dokumenten (Axd<Document> Klassen). Eigene Dokumente lassen sich reicht einfach per Hand oder mit Hilfe des Dokumenten-Wizards erstellen. In der Version 2009 von Dynamics AX erstellt dieser Wizard auch gleichzeitig den benötigenten Service (WCF-Webservice) und andere benötigte Elemente wie (Serviceklassen und Macros). Welche Schritte hierfür benötigt werden ist zum Beispiel im Microsoft Dynamics AX Developer Center beschrieben.
Ein kleines Problem entsteht, wenn das neue Dokument, genauer gesagt die Elemente oder Objekte des Dokuments, in einem Layer (zum Beispiel CUS-Layer) entwickelt wird und später, aus welchen Gründen auch immer, alle Objekte des Dokuments (Query, Ax<Table> Class, Axd<Document> Class) in einen anderen Layer (zum Beispiel VAR-Layer) verschoben werden.
Nach der "Verschiebung" des neuen Dokuments in einen anderen Entwicklungslayer werden durch die AIF-Konfigurationsmasken (siehe Maske Dienstleistungen) allerdings keine Operationen (Insert, Update, Delete, FindKey, etc.) mehr angezeigt. Auch an anderen Stellen, wie zum Beispiel der Endpunktkonfiguration, sind die entsprechenden Operationen nicht mehr auswählbar oder vorhanden.
Der Grund hierfür liegt in der ClassId der Serviceklasse des neuen Dokuments. Dieser, wie auch jedem anderen Objekt, wird beim Import in einen anderen Layer eine neue ID zugewiesen, wenn nicht explizit angegeben wurde, dass der Export und Import mit ID's erfolgen soll. So kann es sein, dass die Klasse mit der ID 40001 nach dem Import in einen anderen Layer die ID 300001 zugeordnet ist.
Da wärend der Konfiguration des AIF's der AOT nach Dokumenten/Services durchsucht wird und für jedes Dokument bzw. jeden Service ein Datensatz in der Tabelle "AifService" sowie ein bis mehrere Datensätze in der Tabelle "AifAction" erzeugt wird, welche alle eine Referenz auf die ClassId der Serviceklasse enthalten, kommt es jetzt zu dem genannten Problem. Der Id 40001 ist nun keine Klasse oder noch schlimmer eine andere Klasse zugewiesen. Auch eine "Aktualisierung" dieser Datensätze über die Aktualisierungsfunktion, welche auf der Maske Dienstleistungen bereit gestellt wird, führt nicht zum gewünschten Erfolg.
Genau in dieser Funktion scheint sich ein kleiner Fehler eingeschlichen zu haben. Dort wird zwar eine Aktulisierung der ClassId für die Datensätze der Tabelle "AifService", aber nicht für die Datensätze der Tabelle "AifAction", durchgeführt.
Um diese Verhalten zu reproduzieren, muss folgendes gemacht werden:
- Erstellen eines neuen AIF Dokuments bzw. AIF Services.
- Über die Maske Dienstleistungen, zu finden unter "Grundeinstellungen -> Einstellungen -> Application Integration Framework -> Dienstleistungen", Funktion "Aktualisieren" das neue Dokument / den neuen Service "aktivieren".
- Über den Button "Servicearbeitsgänge" können nun alle Operationen welche durch das Dokument / den Service bereit gestellt werden eingesehen werden.
- Verschieben aller Elemente des Dokuments / des Services in einen anderen Layer.
- Schritt 2 erneut druchführen.
- Über den Button "Servicearbeitsgänge" werden keine Operation mehr angezeigt.
Um dieses Problem zu lösen, gibt 2 Möglichkeiten.
Entweder manuelles Löschen alle zu diesem Dokument/Service gehörigen Datensätze der Tabelle "AifAction" oder aber man ergänzt die Methode "registerOperations" der Klasse "AifServiceGenerationManager" um ein wenig X++ Code (bei Zeile 43) welcher nicht nur den Namen der Operation aktualisiert sondern auch die ClassId. Da dieser Code sehr einfach ist verzichte ich an dieser Stelle auf ein Beispiel.
Leider tritt dieses Problem auch mit Dynamics AX 2009 Service Pack 1 auf.
In Microsoft Dynamics AX werden alle Informationsmeldungen, Warnungen und Fehlermeldungen in einem Fenster, dem so genannten Infolog, ausgegeben.
Wie Informationen, Warnungen oder Fehlermeldungen erzeugt werden können, ist an vielen Stellen bereits beschrieben. Ein wie ich finde sehr guter Artikel über dieses Thema ist dieser: The user friendly Infolog.
An dieser Stelle soll aber kurz beschrieben werden, wie die Meldungen des Infologs ausgewertet werden können, um zum Beispiel zu ermitteln, ob das Infolog eine Fehlermeldung oder auch eine Warnung enthält.
Zuerst stellt sich die Frage, warum benötigt man überhaupt diese Art von Information da in Dynamics AX die Möglichkeit besteht, verschiedenste Operationen innerhalb einer Transaktion zu Kapsel und diese bei Auftreten eines Fehlers oder Erzeugung einer Fehlermeldung (Stichwort "throw error") automatisch rückgängig zu machen.
Diese Frage soll anhand eines Beispiels beantwortet werden.
Angenommen wir möchten eine Anpassung in Dynamics AX schreiben, welche es ermöglicht, Änderungen an Stücklisten und Arbeitsplänen von Produktionsaufträgen zu automatisieren und alle getätigten Änderungen in einer Transaktion zu kapseln. Anschließend soll noch der Status der Produktions aktualisiert werden. Ebenfalls innerhalb der Transaktion. Zum Beispiel soll der Produktionsauftrag gestartet werden.
Hierfür ist es notwendig verschiedene Standardfunktionen von Dynamics AX zu verwenden, die bereits eine Fehlerbehandlung implementiert haben und somit keine Fehler mehr "melden", welche den Abbruch einer Transaktion zu Folge haben könnten. Somit wird zwar gewährleistet, dass alle "Unterfunktionen" in sich richtig auf Fehler richtig reagieren, aber dennoch könnte eine Dateninkonsistenz entstehen, da nicht alle Operationen rückgängig gemacht werden. Es könnte Beispielhaft sein, dass die Anlage von neuen Stücklistenpositionen und/oder Arbeitsgangpositionen funktioniert, die spätere Statusaktualisierung des Produktionsauftrags aber nicht. Die erstellten Stücklistenpositionen und/oder Arbeitsgangpositionen würden im System gespeichert (bleiben).
Abhilfe für dieses Problem kann duch die Auswertung des Infologs und manuellen Aufrufs von "ttsabort" geschaffen werden.
Mit dem "SysInfologEnumerator" können alle Meldungen, welche in das Infolog geschrieben wurden, durchlaufen werden. Über die Methode "currentException" kann anschließend ausgewertet werden, um was für eine Meldung (Information, Warnung, Fehler) es sich handelt.
Hier ein kurzes Beispiel, wie dies aussehen könnte:
boolean hasError() { SysInfologEnumerator enum; SysInfoAction action; boolean hasError = false; ; //Analyse the infolog to see if there are any warnings/errors enum = SysInfologEnumerator::newData(infolog.infologData()); while (enum.moveNext()) { switch (enum.currentException()) { case Exception::Error: case Exception::Warning: hasError = true; break; }
infolog.add(enum.currentException(), enum.currentMessage(), enum.currentHelpUrl()); } return hasError; }
Es muss allerdings beachtet werden, dass alle Meldungen des Infologs, durch den Aufruf von "SysInfologEnumerator::newData(...)", gelöscht werden. Sollen diesese Meldungen nach der "Auswertung" dennoch dem Benutzer angezeigt werden, müssen diese wieder manuell in das Infolog geschrieben werden (über "infolog.add(..)").
Im Standard von Microsoft Dynamics AX 2009 werden verschiedenste Business Intelligence Funktionen mitgeliefert. Die hierfür benötigen Cubes und Dimensionen erstellt Dynamics AX 2009 unter Verwendung der Analysis-Extension direkt in den Analysis Services des SQL Servers. Dies ist schon einmal sehr schön, da die meiste Arbeit durch die Installationsroutinen abgenommen wird.
Muss oder möchte man allerdings die mitgelieferten Cubes oder Dimensionen an die eigenen Gegebenheiten anpassen, muss zuerst ein BI-Projekt für Visual Studio erzeugt werden, da die Bearbeitung in Visual Studio erfolgt (über die Funktion „BI-Projekt generieren“).
Es können einige „allgemeine“ Einstellungen für die Erstellung eines BI-Projektes über die Funktion „Generierungsoptionen für BI-Projekt“ getätigt werden. Beispielhaft sei hier die Einstellung der Zeitdimensionen genannt.
Allerdings kann es sein, dass man anstatt der erwartet Maske eine Fehlermeldung ausgegeben bekommt. Dies kann besonders bei Verwendung, der für Dynamics AX 2009 bereit gestellten, Demo Daten der Fall sein.

Leider ist diese Fehlermeldung nicht sehr Aussagekräftig.
Hier hilft ein Blick in das Ereignisprotokoll des Dynamics AX Object Servers.

Dies lässt zumindest schon einmal den „groben“ Grund erkennen, was für ein Fehler verursacht wurde bzw. wo der Fehler liegen könnte.
Nach einem Blick in die Tabellendefinition und den Tabellebrowser der angegebenen Tabelle „BIUDMROLES“ wird man feststellen, dass es die angegeben Spalte wirklich nicht gibt. Es gibt aber einen Datensatz mit entsprechender UserGroupId (UserGroupId = PRComplete). Verwendet man nun die Funktion „Gehe zu Haupttabelle“, wird man feststellen, dass es diese Benutzergruppe nicht im System gibt.
Somit ist die Lösung recht einfach. Nachdem der Fehlerhafte Datensatz gelöscht wurde, kann die Maske „Generierungsoptionen für BI-Projekt“ ohne Probleme geöffnet werden.
Microsoft Dynamics AX 2009 bietet die Möglichkeit, den Verlauf eines Dokuments, welches über das AIF exportiert oder importiert wurde zu betrachten. Dies war auch schon mit Microsoft Dynamics AX 4.0 möglich.
Über die Maske "Dokumentverlauf" können alle Dokumente/Nachrichten eingesehen werden, welche über das AIF verarbeitet wurden. Über den Button "Korrelation" ist es sogar möglich, die von der Verarbeitung (schreiben, ändern, lesen, etc.) betroffenen Datensätze anzuzeigen.

So ist es zumindest in der Theorie. In der Praxis sieht es leider etwas anders aus. Nach einem Klick auf den Button "Korrelation" öffnet sich leider nicht wie erwartet die Maske "Dokumentkorrelierung". Stattdessen wird der Debugger (wenn installiert) geöffnet und die Fehlermeldung ausgegeben, dass ein Objekt nicht über die Methode "extendedTypeId" verfügt.

So wie es scheint, hat sich in den Quellcode ein kleiner Fehler eingeschlichen, welcher dazu führt, dass die Maske "Dokumentkorrelierung" niemals geöffnet werden kann. Nach einem Vergleich der Funktionalitäten zwischen Dynamics AX 4.0 und Dynamics AX 2009 kann dieses Verhalten (der Fehler) aber wie folgt beschrieben behoben werden.
- AOT öffnen und zu der Tabelle "AifCorrelation" navigieren.
- Den Quelltext der Methode "displayEntityKey" anzeigen lassen bzw. diese für die Bearbeitung öffnen.
- Folgende Quelltextzeile suchen:
dictField = new DictField(entityKey.parmTableId(), enumerator.currentKey());
- Dieses Zeile abändern in:
dictField = new SySDictField(entityKey.parmTableId(), enumerator.currentKey());
Nach dieser kleinen Quelltextänderung sollte alles wie erwartet funktionierten und die Maske "Dokumentkorrelierung" mit den entsprechenden Datensätzen angezeigt werden.
Im wieder taucht in den Newsgroups und einschlägigen Foren die Frage auf, ob es möglich ist, Dynamics AX 2009 unter Windows Server 2008 und/oder in Verbindung mit SQL Server 2008 zu betreiben.
Die Antwort auf diese Frage lautet eigentlich „Ja“, zugleich aber auch „Nein“.
Offiziell sind die beiden Produkte zwar noch nicht für die Verwendung mit Dynamics AX 2009 freigegeben, aber prinzipiell funktioniert Dynamics AX 2009 auch mit dieser Systemkonfiguration (Kernfunktionalität). Allerdings muss auch erwähnt werden, dass der eine oder andere Punkt bei der Installation bzw. beim Betrieb von Dynamics AX 2009 mit Windows Server 2008 und/oder dem SQL Server 2008 für Verwirrung sorgen kann.
So wird, nach erfolgreicher Installation der Basiskomponenten von Dynamics AX 2009 und anschließendem AOS Start, eine Fehlermeldung im Ereignisprotokoll von Windows Server 2008 erzeugt, welche aussagt, dass Dynamics AX 2009 (genauer der AOS) das gewählte Betriebssystem nicht unterstützt.

Ungeachtet dieser Fehlermeldung, läuft der AOS Dienst von Dynamics AX 2009 unter Windows Server 2008 ohne weitere Probleme. Unschön ist nur, dass diese Meldung bei jedem Start des AOS erzeugt wird.
Für die Verwendung des Enterprise Portals bzw. des Rolecenters muss beachtet werden, dass wie im Installation Guide von Dynamics AX 2009 beschrieben, die Sharepoint Services 3.0 mit SP1 verwendet werden müssen, da frühere Versionen nicht richtig unter Windows Server 2008 laufen.
Ein weiterer Punkt der unbedingt beachtet werden sollte, sind die Reporting-Erweiterungen von Dynamics AX 2009. Eine Installation der Reporting-Erweiterungen ist derzeit leider nur möglich, wenn die Reporting Services des SQL Server 2005 in der Service Pack Version 2 verwendet werden. Sollen die Reporting Services des SQL Server 2008 verwendet werden, scheitert es schon an der Installation der Reporting-Erweiterungen von Dynamics AX 2009. Diese lassen sich in einer solchen Systemumgebung erst gar nicht installieren. Das Setup wird durch eine entsprechende Fehlermeldung abgebrochen.

Dies hat zur Folge, dass die Reporting Services des SQL Server 2008 nicht mit Dynamics AX 2009 verwendet werden können.
Gleiches gilt für die Analysis Extensions von Dynamics AX 2009 in Kombination mit den Analysis Services des SQL Server 2008. Diese lassen sich zwar ohne Problem installieren, aber eine Verarbeitung der Cubes ist nicht möglich, da diese auf Grund von Verarbeitungsfehlern abgebrochen wird.

Schlussendlich bedeutet dies, dass die Verwendung von Windows Server 2008 als Betriebssystem für Dynamics AX 2009 keine Probleme bereiten sollte.
Für die reinen Datenbankdienste von SQL Server 2008 trifft dies ebenfalls zu. In meinen Test konnte ich keinerlei Probleme beim Betrieb mit Dynamics AX 2009 erkennen. Anderes gilt für die Reporting und Analysis Services von SQL Server2008. Deren Verwendung ist leider noch nicht möglich und es müssen weiterhin die Reporting und Analysis Services des SQL Server 2005 verwendet werden um alle möglichen Funktionalitäten von Dynamics AX 2009 zur Verfügung stellen zu können.
Am 9. September 2008 fand der Dynamics Technical Airlift 2008 in Fürstenfeldbruck bei München statt. Wie auch schon im letzten Jahr, richtete sich die Veranstaltung an die eher technisch ausgerichteten Personen (Consultants/Entwickler) aus der Dynamics-Gemeinde.
Ich selbst durfte in diesem Jahr als ATE (Ask the Expert) an dieser Veranstaltung teilnehmen. Der eine oder andere wird mich in dem orangen Poloshirt gesehen haben. 
Insgesamt kann ich nur sagen, es war eine sehr gut organisierte Veranstaltung, auch wenn einige Vorträge, für den einen oder anderen, nicht die gewünschte technische Tiefe hatten. Auch der gemeinsame Informationsaustausch und die vielen Gespräche mit Personen der Dynamics-Gemeinde haben die Veranstaltung positiv abgerundet.
Da Meinungen ja bekanntlich weit auseinander gehen, möchte ich jeden einzelnen bitten, seine Eindrücke und Meinungen zu dem Dynamics Technical Airlift 2008 zu schildern. Wer dies nicht "öffentlich", durch die Kommentarfunktion (hier), machen möchte, kann mir auch gerne eine Email schreiben (Email me).
Ich möchte auch die jenigen bitten, die nicht an dieser Veranstalltung teilgenommen haben, mir ein kurzes "Feedback" zukommen zu lassen. Besonders die Erwartungen an eine solche Veranstaltung und/oder die Community im Allgemeinen würden mich interessieren.
Bitte beachtet, dass alle Kommentare erst durch mich "überprüft" werden müssen, bevor sie angezeigt werden.
Alle frei erhältlichen Dokumente über Microsoft Dynamixs AX 2009 stehen jetzt über Windows Live SkyDrive für jedermann frei zur Verfügung.
Vielen Dank an Arijit Basu, der sich die Arbeit gemacht hat, diese dort zum downlaod zur Verfügung zu stelllen.
Mehr Informationen hierzu gibt es im Blog von Arijit Basu.
Hier der "direkt" Link zu den Dokumenten: AX 2009 Documents
Wie bereits im diesem Artikel "Fehlermeldung beim Starten des Microsoft Dynamics AX Clients" beschrieben, kann es zu Fehlermeldungen beim Starten des Dynamixs AX 4.0 Client kommen.
Eine weitere Fehlermeldung, welche erzeugt werden kann ist "Incompatible ext. version". Es ist auch möglich, dass diese sogar mehrfach ausgegeben wird.
Grund hierfür ist meist ein Problem mit der TAPI-Integartion des CRM Moduls, bzw. genauer gesagt, ein Problem mit den eingestellten Wählregeln/Standorte der Windows Telefon- und Modemoptionen.
Die Behebung des Fehlers ist eigentlich ganz einfach.
- Wenn die TAPI-Integration nicht genutzt wird, kann diese deaktiviert werden.
Wie dies genau geht kann in diesem Artikel "Fehlermeldung beim Starten des Microsoft Dynamics AX Clients" nachgelesen werden.
- Wenn die TAPI-Integration verwendet werden soll, muss ein neuer Standort in den Windows Telefon- und Modemoptionen erstellt werden.
Das Erstellen eines neuen Standorts erfolgt über "Start -> Systemsteuerung -> Telefon- und Modemoptionen" auf dem jeweiligen Clientcomputer (pro Benutzer). Dort sollte, wenn vorhanden, ein bestehender Standort gelöscht werden und ein neuer angelegt werden.
Manchmal ist es möglich, dass beim Starten des Microsoft Dynamics AX 4.0 Clients eine oder meherer Fehlermeldungen in einem Infolog-Fenster ausgegeben werden.
Diese Fehlermeldung könnten z.B. "Corrupted ini file" sein.
Die große Frage ist nun, woher kommt diese Fehlermeldung bzw. wodurch wird diese erzeugt. Leider ist die Fehlermeldung, welche im Ereignisprotokoll gefunden werden kann, meist auch nicht besonders hilfreich.
Sollten solche, eher unerklärlichen Fehlermeldungen beim Starten des Dynamics AX Client ausgegeben werden, lohnt sich oft ein Blick in die Systemkonfiguration, welche über Verwaltung, Einstellungen, System, Konfiguration aufgerufen werden kann.
Der Grund für diese Fehlermeldung könnte die aktivierte Telefonieintegration des CRM Moduls sein. Wird diese deaktiviert, sollte die Fehlermeldung nicht mehr erzeugt werden.
Für jede Tabelle können Systemfelder wie Erstellt von, Geändert von, Erstellungsdatum, Erstellungszeit oder Änderungsdatum von Dynamics AX aktiviert werden. Diese Felder werden durch Dynamics AX automatisch gefüllt. Wird zum Beispiel ein neuer Datensatz erzeugt, füllt Dynamics AX die Systemfelder mit den entsprechenden Daten.
Es gibt aber Situationen wo man selber Einfuß auf die Werte dieser Felder nehmen muss. Ein Beispiel hierfür könnte eine Datenübernahme sein, bei der die Informationen über den Ersteller oder das Erstellungsdatum des Datensatzes nicht verloren gehen dürfen.
Wie dies gehen kann zeigt dieses kleine Beispiel:
YourTable table; ; ttsbegin;
//can only be called on server tier. -> method must be executed on server tier. new SkipAOSValidationPermission().assert(); table.skipAosValidation(true);
table.YourField = "Value";
table.overwriteSystemfields(true);
//set your own values for the system fields. table.(fieldnum(Table1, ModifiedDate)) = today() - 2; table.(fieldnum(Table1, CreatedDate)) = today() - 5; table.(fieldnum(Table1, CreatedBy)) = "TEST";
table.insert(); ttscommit;
table.skipAosValidation(false);
Allerdings können die Systemfelder nur beim Erstellen eines neuen Datensatzes "von Hand" festgelegt werden.
Wie das Ändern von Werten der Systemfelder bei bereits bestehenden Datensätzen geht demonstriert die Klasse "BatchRun", Methode "runJob" und "finishJob". Kurz gesagt wird genau genommen der Datensatz nicht geändert, sondern es werden nur die Daten des bestehenden Datensatzes in den neuen Datensatz kopiert (mit newBuffer = oldBuffer.data()) und dann wie bereits beschrieben die Systemfelder mit eigenen Werten befüllt. Dann wird der bestehnde Datensatz gelöscht und der neue Datensatz in die Datenbank geschrieben.
So nach und nach sind immer mehr Informationen über die nächste Version von Microsoft Dynamics AX im Internet erhältlich, die einen ersten Einblick in das verschaffen, was alles an Neuerungen mit Dynamics AX 2009 kommt.
Arijit Basu hat in seinem Blog einen Artikel über einige der Änderungen gepostet. Der Artikel beschreibt unter Anderem die Änderungen am Benutzerinterface, das neue Role Center, die neuen Workflow-Features sowie die Erweiterungen am Enterprise Portal.
Weiterhin ist auf Channel9 ist ein Video zu finden, welches das Enterprise Portal von Dynamics AX 2009 und dessen System-Architektur erläutert. Es wird gezeigt, wie eigene Controls (mit ASP.NET) für das Enterprise Portal erstellt werden können und wie diese in das Enterprise Portal sowie das Role-Center eingebunden werden können.
Im Microsoft Dynamics AX Developer Center wurde für Dynamics AX Entwickler eine neue Webcast Serie gestartet.
Auszug:
"On this page you will find videos designed for all Microsoft Dynamics AX developers, from the novice to the professional. New videos are added regularly, so check back often."
Derzeit ist nur ein Webcast über "Dynamics Links between parent and child Forms" erhältlich. Gilt zu hoffen, dass in der nächsten Zeit noch weitere nützliche Webcast folgen.
Heute habe ich eine Email erhalten, in der folgendes zu lesen war:
"...Herzlichen Glückwunsch! Wir freuen uns, Ihnen den Microsoft MVP Award 2008 verleihen zu können..."
Mir wurde der MVP für Microsoft Dynamics AX verliehen. Wow!
Ich möchte mich an dieser Stelle bei allen Teilnehmern der Microsoft Dynamics AX Community bedanken, die es überhaupt ermöglich haben, dass mir dieser Titel verliehen wurde. Besonderen Dank möchte ich an Helmut Wimmer [axaptafreak] und Mathias Füßler [jinx, meinen Co-Autor, oder bin ich seiner? ] aussprechen, die mich immer tatkräftig unterstützt haben.
Natürlich werde ich jetzt nicht aufhören, weiterhin Hilfestellung bei Fragen zum Thema Dynamics AX zu geben. Ich sehe diese Auszeichnung als Ansporn, mich auch weiterhin aktiv in der gesamten Dynamics AX Community zu beteiligen.
Nochmals, danke an euch alle.
In Foren, Newsgroups oder auch in persönlichen Gesprächen ergibt sich oft die Frage, wo man anfangen soll/kann um den Umgang mit Microsoft Dynamics AX zu lernen.
Gerade für Einsteiger oder Anfänger ist es machmal schwer, die Informationen zu finden, die gerade benötigt werden. Dank der Dynamics AX Community, welche zum Glück immer größer und besser wird, stellt das Internet mit seinen vielen Dynamics AX Blogs, Foren, Newsgroups und nicht zuletzt dem Microsoft Dynamics AX Developer Center eine sehr gut Informationsquelle dar.
Trotzdem hört man oft die Frage, ob es denn keine Bücher über Microsoft Dynamics AX gibt. Um etwas mehr Klarheit zu schaffen, welche Bücher über Microsoft Dynamics AX erhältlich sind, hier eine Liste aller Bücher die mir bekannt sind:
In Kürze soll ein neues Buch über Microsoft Dynamics AX erscheinen. Im Schwerpunkt soll es sich mit dem Thema Qualitätssicherung beschäftigen. Titel des Buchs ist "Quality Assurance for Dynamics AX-Based ERP Solutions".
Ein Auszug der einzelnen Themenpunkte:
Customization Best Practices backed by theory
Learn rapidly how to test Dynamics AX applications
Verify Industry Builder Initiative-compliance of ERP software
Get ready-made testing templates
Code, design, and test a quality Dynamics AX-based ERP solution
Genaueres über das Buch kann man hier erfahren.
Alexei Eremenko hat auf seinem Blog einige Artikel über die kommende Version von Microsoft Dynamics AX und dessen neue Features veröffentlicht. Da diese leider in Russich geschrieben sind, hier eine kurze Zusammenfassung:
- Aus Microsoft Dynamics AX 5.0 wird Microsoft Dynamics AX 2009.
- Geänderte Benutzeroberfläche (Office 2007 Style, inkl. Ribbon's).
- Neue "Funktion" Rollcenter, die dem Benutzer schnellen Zugriff auf die, für seine Arbeit, relevanten Daten geben soll.
- Unterstützung des UNION Befehl's für SQL Abfragen, bei Verwendung der Query-Klassen.
- Neuer Exception-Typ "DublicateKeyException" zur Ausnahmebehandlung wenn ein Datensatz schon besteht.
- Die SQL DML bulk Anweisungen erlauben die Verwendung von Inner- und Outer-Joins.
- Zugriff auf das Ergebnis der "update_recordset" Anweisung, um zu bestimmen wie viele Datensätze durch die Operation geändert wurden.
- CrossCompany-Unterstützung für Datenbankabfragen (Daten aus unterschiedlichen Mandaten können in einer SQL Anweisung behandelt werden).
Wer die orginalen Artikel einmal selber lesen möchte, findet die einzelnen Blog-Posts hier: (Die Links verweisen auf die Übersetzung der Artikel ins Englische)
Einen ersten Ausblick auf die "neuen" Quellcodeverwaltungsfeatures in Microsoft Dynamics AX 5.0 zeigt der Screencast "Version control in MorphX" auf Channel9.
http://channel9.msdn.com/Showpost.aspx?postid=367024
Ich zitiere: "This screencast is a preview of the version control system integration options in the next release of MorphX - the IDE of Dynamics AX. It shows a side-by-side comparison of the integration options with Team Foundation Server, Visual Source Safe, and MorphX VCS. The latter is a simple, yet powerful alternative without any additional infrastructure requirements. The last half of the screencast gives a demonstration of MorphX VCS."
Durch die neuen Features die MorphX VCS mit sich bringt, sowie die Möglichkeit Visual Studio Team System, oder genauer der Team Foundation Server, (nicht nur) als Quellcodeverwaltung zu verwenden, sollte nun für jeden ein "passendes" Quellcodeverwaltungsystem bereit stehen.
Vielen Dank an dieser Stelle an Michael Fruergaard Pontoppidan (http://blogs.msdn.com/mfp/default.aspx) für diesen und die bisherigen Screencasts über Microsoft Dynamics AX.
Die Version 4.0 von Microsoft Dynamics AX enthält eine neue Funktion ("Nach Raster filtern" oder "Filter by Grid") mit der die Datenfilterung direkt in einem Grid ermöglicht wird.

Die Funktion "Nach Raster Filtern" kann entweder über die Tastenkombination "STRG + G", über die Symbolleiste oder den Menüpunkt "Bearbeiten - Filtern - Nach Raster filtern" aktiviert werden.
Das "Nach Raster filtern" ist per Standard deaktiviert und muss somit immer manuell durch den Benutzer aktiviert werden. Leider wird in den benutzerspezifischen Einstellungen für eine Maske nicht gespeichert ob das "Nach Raster filtern" aktiviert oder deaktiviert ist. Somit muss die Funktion, wenn diese verwendet werden soll, für jede Maske und nach jedem Schließen einer Maske erneut aktiviert werden.
Soll nun für eine Maske die Funktion "Nach Raster filtern" dauerhaft aktiviert sein, ist eine kleine Anpassung im Quelltext der Maske notwendig.
Als erstes muss die Eigenschaft "AutoDeclaration" für das Grid Control, bei welchem die Funktion "Nach Raster filtern" aktiviert werden soll, auf "Yes" gesetzt werden. Weiterhin muss die Methode "run" der Maske, nach dem Aufruf von "super", um diese Quellcodezeilen ergänzt werden:
Grid.enter(); this.task(2855);
"Grid" ist hierbei der Name des Grid Controls, für welches die Funktion "Nach Raster filtern" aktiviert werden soll.
Soll gleichzeitig noch ein Filter für die Datensätze aktiviert werden, erfolgt dies über die Ranges der Datasource-Querys. Hierbei kann wie gewohnt eine Range für die entsprechende Query definiert werden. Wird die Range für ein Feld gesetzt, welches in dem Grid Control angezeigt wird, wird der Wert der Range entsprechend in der "Filterzeile" angezeigt.
Möchte man die schon gepflegten Daten eines Dynamics AX 3.0 System über exportieren/importieren in ein Dynamics AX 4.0 SP1 System übernehmen, wird bei diesem Vorgang leider eine Fehlermeldung erzeugt, dass ein Importieren in das Dynamics AX 4.0 SP1 System nicht möglich ist, da die Daten aus einem älteren System stammen.
Dies ist soweit auch in Ordnung, da sich Tabellen und Felder von Version 3.x zu Version 4.0 SP1 verändert haben (Namensänderungen, Feldergänzungen, etc.). Da bei einigen Tabellen aber nur Felder weggenommen wurden, könnte man theoretisch die Daten aus dem „alten“ 3.x System übernehmen. Ein Beispiel hierfür ist der Kontenplan (LedgerTable).
Damit dies funktioniert muss aber eine Änderung an der aus dem Dynamics AX 3.x System exportierten „.def“ Datei vorgenommen werden. Die erste Zeile der „.def“ Datei muss so bearbeitet werden, dass diese wie folgt lautet:
Wenn beim Export als Dateityp „Binär“ gewählt wurde: "EXPFORMAT VER. 4.01","Binary"
Wenn beim Export als Dateityp „Komma“ gewählt wurde: "EXPFORMAT VER. 4.01","Comma"
Wurde die „.def“ Datei entsprechend angepasst, kann es zwar sein, dass beim Import Fehlermeldungen über nicht vorhandene Felder erzeugt werden aber der Importvorgang an sich funktioniert nun.
Anzumerken ist nur noch, dass diese Version der „Datenübernahme“ nur für Spezialfälle gewählt werden sollte. Ein Datenupdate, mit den von Microsoft bereitgestellten Tools, sollte vorgezogen werden.
Für Microsoft Dynamics AX 4.0 SP1 stehen auf den Microsoft Webseiten 2 PDF Dokumente zur Verfügen, welche die Hardwareanforungen an eine Systemumgebung mit 100 und 200 Benutzern beschreiben.
http://www.microsoft.com/dynamics/ax/product/hardwaresizing.mspx
Man sollte die dort getätigten Aussagen aber eher als eine Art "grundlegende Richtlinie" verstehen, da die realen Hardwareanforderungen eines einzelnen Dynamics AX System, bedingt durch die spezifischen Anpassungen, in einzelnen Punkten variieren können.
Möchte man nach einem Upgrade von Microsoft Dynamics AX 4.0 auf Microsoft Dynamics AX 4.01 einen neuen Benutzer anlegen erhält man die Fehlermeldung "".
Dies läßt erst einmal auf ein Problem im Quellcode von Microsoft Dynamics AX schließen.
Grund für die Fehlermeldung ist aber kein Fehler im Quellcode, sondern ein fehlerhafter Datensatz in der Tabelle "SysPerimeterNetworkParms". In diesem Datensatz steht im Feld "PNType" ein ungültiger Wert.
Wird dieser Wert auf einen gültigen Wert (None) geändert, können auch wieder neue Benutzer im System angelegt werden.
Folgender Job kann zur Behebung des Problems verwendet werden: (Verwendung auf eigene Gefahr. Es wird keine Garantie oder Haftung für die Funktion und Richtigkeit des Quellcodes gegeben. )
static void CorrectAxaptaUserImportError(Args _args) { SysPerimeterNetworkParams p; DataArea a; ; while select a { changecompany(a.Id) { p = null; ttsbegin; while select forupdate p { p.PNType = PerimeterNetworkType::None; p.update(); } ttscommit; } } }
Im Microsoft PartnerSource ist ein Dokument erhältlich, welchen den Updateprozess beschreibt, der durchzuführen ist, wenn man ein Update von Microsoft Dynamics AX 4.0 auf Microsoft Dynamics AX 4.01 durchführen möchte. Alles in allem ist dieses Dokument eine sehr gute Informationsquelle, die fast alle Einzelheiten, die bei dem Update zu beachten sind, erläutert. Bedauerlich ist nur, dass eine sehr wichtige "Kleinigkeit" nicht in diesem Dokument erwähnt wird. Hält man sich strickt an die Dokumentation, so wird man leider feststellen, dass sich der AOS nach der Installation von Microsoft Dynamics AX 4.01 nicht mehr starten lässt. Es wird zwar ein Eintrag im EventLog erzeugt, dieser ist aber nicht besondern hilfreich (Error 110). Grund für diese Fehlermeldung sind die beiden StoredProzedures die ab Microsoft Dynamics AX Version 4.0 in jeder Microsoft Dynamics AX Datenbank vorhanden sein müssen. Da die Datenbank an sich nicht "geupdatet" wird, werden diese SP`s ebenfalls nicht geändert und bleiben damit auf dem Stand von Microsoft Dynamics AX 4.0. Und leider scheint Microsoft Dynamics AX 4.01 genau mit diesen SP`s nicht zusammen arbeiten zu können. Die Lösung des Problems gestaltet sich zum Glück recht einfach: Die SP's müssen einfach nur gegen die beiden SP's einer Microsoft Dynamics AX 4.01 Datenbank ausgetauscht werden und schon funktioniert der AOS wie erwartet.
Wie schon unter "Screenshots von Dynamics AX Masken erstellen" beschrieben, war es auch schon zu Dynamics AX 3.0 möglich, automatisierte Screenshots von Dynamics AX Masken erzeugen zu lassen, um diese dann später in seinen Dokumentationen zu verwenden. Leider enthält Dynamics AX 4.0 die hierfür benötigten Klassen nicht mehr. Allerdings soll bald ein Tool für Dynamics AX 4.0 erscheinen (TaskRecorder), welches diese und noch weitaus mehr Funktionalitäten bietet. Wer sich dieses Toll einmal genauer ansehen möchte und einen PartnerSource-Zugang besitzt, der kann sich im PartnerSource eine Beta Version dieses Tools downloaden. Genaue Informationen über den TaskRecoder (Features, Installation, etc.) können ebenfalls über das PartnerSource bezogen werden. Nach meinen ersten Erfahrungen wird hiermit eine gute Basis geschaffen um eine einheitliche und schnell zu erstellende Dokumentation von Prozessen und Anpassungen zu erstellen.
Ein weiteres Problem beim Update auf die neue Version Microsoft Dynamics AX 4.0 kann der Name des Unternehmenskontos sein. Wird ein Unternehmenskonto verwendet, dass in seinem Namen ein „&“ enthält, z.B. „A&B“, werden einige Prozesse beim „Datenaktualisierung nachsynchronisieren“ mit einem Fehler abgebrochen. Im Ereignislog ist dann ein Eintrag des Dynamics AX 4.0 Servers zu finden, der wie folgt lautet (Ausschnitt): „…[Microsoft][ODBC SQL Server Driver][SQL Server]Falsche Syntax in der Nähe von '&'.. The SQL statement was…“ Daraus wird ersichtlich, das dass „&“ Zeichen als SQL Statement erkannt wird und die SQL Anweisung so fehlerhaft interpretiert wird. Dieses Problem kann nur gelöst werden, indem man in dem zu updatenden Microsoft Dynamics AX 3.0 ein neues Unternehmenskonto erstellt das kein „&“ Zeichen beinhaltet (Am einfachsten geht dies mit der Dublizierfunktion der Unternehmenskonten).
Für die Planung und Durchführung eines Updates stehen folgende Informationsquellen zur Verfügung:
- Microsoft Dynamics AX Upgrade Tools Guide (PDF Dokument, Erhältlich im PartnerSource)
- Microsoft Dynamics AX 4.0 Implementation Guide (CHM File, Dynamics AX 4.0 Dokumentation)
- Inside Microsoft Dynamics AX 4.0 (Buch, Microsoft Press)
Diese enthalten eine gute Beschreibung der einzelnen Schritte die erforderlich sind, um von der Version 3.0 auf die Version 4.0 von Microsoft Dynamics AX zu updaten.
Allerdings können noch einige Probleme bei dem Updateprozess entstehen, die leider nicht Besprochen werden und für die auch in den bekannten Newsgroup, Blogs und Communitys noch keine Lösungsvorschläge gibt.
So sollte ein Upgrade immer in dem Layer durchgeführt werden, in dem die Anpassungen durchgeführt wurden (z.B. CUS oder VAR). Dies hat zur Folge das man u.U. die Anwendung mehrfach kompilieren muss, da man erst nach dem einlesen der Lizenzdatei zugriff auf diese Layer erhält.
Weiterhin kann man beim Durchführen der Synchronisierung folgenden Fehler erhalten: "Cannot execute a data definition language command on (). The SQL database has issued an error."
Ursache hierfür kann sein, dass der ConfigurationKey "CSESpain" ist in dem Microsoft Dynamics AX 3.0 System, welches geupdatet werden soll, nicht angeschaltet ist/war. Dadurch sind drei Felder ("Action", "CustVendParameter", "CustVendAccount") der Tabelle "SalesPurchaseCycle" deaktiviert, die allerdings den eindeutigen Index "SalesPurchaseCycle" bilden. Dadurch werden Datensätze in die Tabelle geschrieben, die nicht dem eindeutigen Index entsprechen. Beim Update auf Microsoft Dynamics AX 4.0 wird dieser Index überprüft bzw. neu geschrieben und das Synchronisieren wird mit einem Fehler abgebrochen, da die Datensätze der Tabelle nicht eindeutig sind.
Das Problem kann gelöst werden, indem man auf der Tabelle "SalesPurchaseCycle" den eindeutigen Index "SalesPurchaseCycleIdx" auf "Enabled = NO" setzt. Anschließend sollten alle Datensätze in dieser Tabelle in allen Unternehmen gelöscht werden und der Index "SalesPurchaseCycleIdx" wieder auf "Enabled = YES" gesetzt werden.
Die Deaktivierung des ConfigurationKey "CSESpain" reicht leider nicht aus, da es dann zu Problemen beim "Datenaktualiserung nachsynchronisieren" kommen kann, da dort die einzelnen Datensätze überprüft werden (5 Prozesse werden deswegen mit einem Fehler beendet).
Weiterhin sei noch angemerkt, dass alle Anpassungen in Bereich der "Forms" zu erheblichen Problemen beim Codeupgrade führen können. Viele Formelemente wurden in der neuen Version 4.0 unbenannt, was dazu führen kann, dass eine einzige Anpassung (z.B. Änderung nur einer Formproperty) mehrere hundert Fehler erzeugen kann.
Bsp.: Änderung einer Property der Form "CompanyInfo" im upzudatenden Microsoft Dynamics AX 3.0 System führte zu 126 Fehlern im Microsoft Dynamics AX 4.0 System.
Deswegen sollte man vor einem Update genauestens überlegen/überprüfen, ob es überhaupt Sinn macht die getätigten Anpassungen mit zur neuen Version (4.0) zu migrieren.
Oft können getätigte Anpassungen durch Erweiterungen im Standard abgelöst werden, die eine ähnliche Funktionalität bieten. In machen Fällen ist es unter Berücksichtigung der benötigten Zeit sogar Sinnvoller, die Anpassung erneut im Microsoft Dynamics AX 4.0 System vorzunehmen.
Eine Migration der Anpassungen sollte nur in Erwägung gezogen werden, wenn keine andere Lösung gefunden werden kann.
Auszug aus der aktuellen Pressemitteilung von Microsoft:
Microsoft gibt Startschuss für Microsoft Dynamics AX 4.0
Microsoft bietet die neue Version der kaufmännischen Software Microsoft Dynamics AX ab sofort auf dem deutschen Markt an. Microsoft Dynamics AX 4.0 ist eine anpassbare Businessmanagementlösung, die Unternehmen hilft, fundierte und profitable Geschäftsentscheidungen zu treffen. Die Software, deren Nutzeroberfläche allen anderen Produkten von Microsoft gleicht, lässt sich nahtlos mit Microsoft Office 2003 und der Microsoft Windows Server System-Familie verzahnen. Microsoft Dynamics AX 4.0 richtet sich an mittelständische Unternehmen und den gehobenen Mittelstand.
mehr unter:
http://www.microsoft.com/germany/presseservice/detail.mspx?id=531742
Im Mai 2007 soll im Vieweg Verlag ein neues Buch über Microsoft Dynamics AX 4.0 erscheinen.
Der Schwerpunkt des Buches soll auf den Grundlagen von Dynamics Ax 4.0 und den Neuerungen zur Vorgängerversion liegen. Genaueres ist noch nicht bekannt.
Seit ende Juli / Anfang August steht auch die lokalisierten Versionen von Microsoft Dynamics AX 4.0 für Microsoft Partner bereit, die einen PartnerSource Zugang haben.
Lokalisierungen stehen u.a. für volgende Länder zur Verfügung
Denmark France Germany Great Britain Ireland
Eine ausführliche Liste ist ebenfalls im PartnerSource erhältlich.
Wer auf der Suche nach Dokumentation zu / über Dynamics Ax 4.0 ist, sollte mal einen Blick auf diese Seite werfen: Using Microsoft Dynamics AX
Es ist nicht gerade einfach, einen Screenshot einer einzelnen Maske (z.B. Debitoren) von Dynamics Ax zu erstellen.
Verwendet man die Windows-Boardmittel, ist in dem erzeugten Screenshot immer der gesamte Dynamics AX Bildschirm enthalten. Da Dynamics AX eine MDI Anwendung ist, erkennt Windows immer nur den gesamten Dynamics AX Bildschirm und nicht wie gewollt, die in diesem "Hauptbildschirm" aktive Dynamics AX Maske (z.B. Debitoren).
Abhilfe kann hier mit zahlreichen zusätzlichen Tools geschaffen werden, die es ermöglichen, nur einen bestimmten Bildschirmausschnitt in den Screenshot zu übernehmen (z.B. Hardcopy oder Paintshop Pro).
Aber geht das nicht doch etwas einfacher?
Klare Aussage: Ja es geht einfacher! Dynamics AX ist in der Lage, automatisch von einer oder mehreren Masken gleichzeitig (natürlich einzeln und nacheinander) Screenshots zu erzeugen.
Der AOT von Dynamics AX beinhaltet unter dem Zweig "Forms" die Form "sysDocCaptureForm" sowie im Zweig "Menuitems/Display" das gleichnamige MenuItem. Öffnet man eines dieser beiden Objekte, öffnet sich die Maske "Erfassungsserie", die stark an ein übliches Journal erinnert. Hier kann eine Art "Erfassungsjournal für Screenshots" angelegt werden. Es können allgemeine Informationen wie Ablageverzeichnis für die Screenshots im Dateisystem oder deren Format bestimmt werden. Über den Button "Schritte" kommt man zu der Maske "Schritte erfassen", auf der die einzelnen Masken bestimmt werden können, von denen automatisch Scrennshots erstellt werden sollen. Die Screenshots können schließlich über den Button "Erfassen" auf der Maske "Erfassungsserie" erstellt werden. Hilfreich für die Erstellung automatischer Screenshots ist die Funktion, von jedem Reiter einer Maske einen neuen Screenshot zu erstellen. Dies kann mit dem Haken "Erfassen" auf der Maske "Schritte erfassen" eingestellt werden.
Nach meiner Meinung ein nettes kleines Feature, was die Arbeit durchaus erleichtern kann. Schade ist nur, dass der Dynamics AX Standard keine "direkte" Aufrufmöglichkeit hierfür bietet.
Es gilt aber noch anzumerken, dass man für die Verwendung dieses Tools die Berechtigung auf dem SecurityKey "SysDevelopmentMorphX" braucht.
Das erste Buch über das neue Microsoft Dynamics AX 4.0 soll so im August-September 2006 über Microsoft Press veröffentlicht werden.
Sprache: englisch ISBN: 0-7356-2257-4 Preis: ca. 60-70 EUR
Das Buch soll folgende Themen behandeln (engl. Orginalauszug):
Dive deep in to the architectural details of Microsoft Dynamics AX to make relationships clear and development tasks easier. The first part of the book is aimed at consultants and developers who are new to Microsoft Dynamics AX but have backgrounds in business application development using traditional languages, frameworks, and tools.
It describes the architecture and development environment and explains key application frameworks that developers need for their customization, extension, and integration projects. The second part of the book is a reference guide for developers who work with Microsoft Dynamics AX deployments, with information on developing new functionality and supporting users.
It covers more complex development concepts such as advanced forms and reports, reflection over the application metadata, performance, upgrades, migration, and setup. This is the first book written by the Microsoft product group architects and the first to take developers deep inside Microsoft Dynamics AX.
Wie auf den Webblogs von Tom Braekeleirs (MBS), Pale Agermark (MBS) sowie Satya Nadella (MBS) zu lesen ist, ist die neue Version von Microsoft Dynamics Ax (endlich) fertig (Microsoft Dynamics Ax 4.0).
Für alle MBS Partner, die Zugang zum PartnerSource oder MSDN haben, soll diese dann ab Montag zum download bereit stehen.
Seit Heute ist das Microsoft Dynamics AX 3.0 Kernel Rollup 2 verfügbar. Es kann über die PartnerSource Webseite bezogen (download) werden.
Ein kurzer Auszug aus der Fix- bzw. Änderungsliste:
- Erweiterte PDF Funktionalität
- SQL 2005 Stabilisierung
- AOS/COM Stabilisierungen
- Memofelder und Unicode
Eine ausführliche Fixliste ist in dem Download des Kernel Rollup 2 enthalten.
Wichtig ist aber, dass das Kernel Rollup 2 nur auf Dynamics Ax 3.0 Systemen installiert werden darf, die mindestens das Service Pack 2 installiert haben.
Um auf einen Dynamics Ax Object Server, der durch eine Firewall gesichert ist, zugreifen zu können müssen in der Firewall folgende Regeln vorhanden sein.
1. Allow all incoming TCP traffic on AOS Port to AOS IP. 2. Allow all outgoing TCP traffic. 3. Allow all incoming UDP traffic on Port 2712 to AOS IP.* 4. Allow all outgoing UDP traffic.*
Weiterhin muss die Firewall UDP NAT unterstützen.*
Möchte man weiterhin noch eine lokale Firewall auf den jeweiligen Clients betrieben sollte diese wie folgt Konfiguriert sein.
1. Allow all outgoing TCP traffic on AOS Port to AOS IP. 2. Allow all incoming TCP traffic for Dynamics Ax Client (ax32.exe). 3. Allow all outgoing UDP traffic on Port 2712 to AOS IP.* 4. Allow all incoming UDP traffic for Dynamics AX Client (ax32.exe).*
* Sollte die verwendete Firewall kein UDP NAT untestützen bzw. sollten die entsprechenden UDP Regeln nicht eingepflegt werden können, besteht noch die Möglichkeit, dass man dem Dynamics Ax Client mittels -aos=host:port direkt einem AOS zuweißt. Damit versendet der Dynamics AX Client keine Broadcast mehr über UDP, um die im Netz befindlichen Dynamics AX Object Server zu ermitteln, sondern Verbindet sich direkt mit dem über "host:port" angegebenen AOS. Allerdings gibt es hierbei die Einschränkung, dass keine AOS Cluster verwendet werden können, da der Client sich immer auf den angegebenen AOS verbindet.
Dynamics Ax erlaubt das mehrmalige Anmelden unter einer Benutzerkennung. So kann ein Benutzer eine beliebige Anzahl an Sitzungen mit seiner Benutzerkennung öffnen.
Möchte man aber die mögliche Anzahl an Sitzungen unter einer Benutzerkennung begrenzen, ist dafür eine Anpassung der Info Klasse notwendig.
Fred Shen beschreibt in seinem Blog, wie diese Anpassung auszusehen hat.
Langsam ist der Zeitpunkt gekommen, zu dem sich auch ein Dynamics Ax Entwickler mit dem Thema .NET beschäftigen sollte.
Ich stimme fast jedem zu der sagt, dass man bei Dynamics Ax 3.0 eigentlich keinerlei .NET Kenntisse benötigt. Allerdings wird sich das mit Dynamics Ax 4.0, durch die erweiterte Integration zwischen Dynamics Ax und .NET, ändern.
Deshalb sollte man nicht auf den Release von Dynamics Ax 4.0 warten, sondern sein Wissen schon jetzt erweitern.
Einen guten Einstieg in die .NET Welt bietet die MSDN Webcast-Serie von Bernd Marquardt, Get Sharper Now! - C# für Einsteiger und Umsteiger (ich gehe davon aus, dass die Sprache C# die erste Wahl sein wird, jedenfalls für die meisten Dynamics Ax Entwickler).
Oft muss von Dynamics Ax aus z.B. auf eine Datei zugegriffen werden. Hierbei muss man beachten, dass die Pfadangabe zu der Datei eine Escape-Sequenz darstellt/enthält.
Bsp.: str file = "C:\\test\\test.csv";
Es existiert aber eine, soweit mir bekannt allerdings undokumentierte, Möglichkeit den Dateipfad auch ohne Escapezeichen anzugeben (raw string).
Bsp.: str file = @"C:\Test\test.csv";
Zusätzlich kann man bei Verwendung von @"" auch Zeilenumbrüche innerhalb des String zu verwenden/schreiben.
Bsp.: str text = @"Das ist ein Text mit mehr als einer Zeile";
|