View
4.773
Download
5
Embed Size (px)
DESCRIPTION
Microsoft dynamics ax 2012 development introduction part 2/3 This includes overview of X++
Citation preview
MICROSOFT DYNAMICS AX 2012 DEVELOPMENT INTRODUCTION
ByAli Raza Zaidi
Contents
• Objective.• Prerequisite for Audience• Dynamics Ax • Microsoft Dynamics AX 2012 Architecture• Data Dictionary • User Interfaces• X++ Overview • X++ Control Statements• Classes and Objects• Accessing the database• Exception Handling• Conclusion
X++ OVERVIEW
X++ is the programming language used in MorphX IDE. X++ resembles other popular languages such as C# and Java. X++ includes many integrated SQL commands; X++ is object-oriented language and provides a clean and efficient
object-based development platform. Data Aware Includes keywords such as firstFast, forceSelectOrder,
and forUpdate, as well as a database query syntax application aware client, server, changecompany, and display
Code EditorJobsCompiler The DebuggerCompare
Development Tools(Contd.)
Reverse EngineeringSimplify collection Extract relationships Integrate and view collections in Microsoft Office Visio as UML diagrams
Naming conventions
Naming conventions contribute to consistency and to making the application easier to understand.
{business area name} + {business area description} + {action performed (for classes) or type of contents (for tables)}
Examples:
• CustJournalPrintOutInvoice • PriceDiscAdmDelete• PriceDiscAdmSearch• PriceDiscAdmName • PriceDiscAdmTrans
Comments
Single line “//” Block comments “/* */” To do comments “TODO.” To do comments appear in the compilers Tasks tab page./// <summary> /// This is an XML comment with tags to distinguish sections. /// </summary>
X++ CONTROL STATEMENTS Data Type Declaration
Keyword Description/Example
String str “any string”Integer int 2356Real Real 3.14Date date 24\11\2010Enum Must be declared
as a Base Enum first
Enum values are represented internally as Integers.
Boolean boolean True/FalseTime timeOfDay 15:23:08utcDateTime utcDateTime 9/28/2008
07:11:02 am
Guid guid Global Unique Identifier, a reference number which is unique in any context
Int64 Int64 A large integer, represent by 64 bits.
X++ CONTROL STATEMENTS(Contd.)
Composite Date Types
Variable Declaration:dataType variableIdentifier;
Array Declaration: real realUnlimtedArray[]; // Unlimited index values real realLimitedArray[10]; // maximum of 10 values
X++ CONTROL STATEMENTS(Contd.)
Containers: A variable that can contain different types and values of simple and extended data types, including
arrays and other container variables. Classes cannot be put into containers.
container c; // the container is declared int i, j; str txt; ; c = [10, 20, "test"]; // the container has 3 values set print conPeek(c, 3); // the third element is printed [i,j,txt] = c; // Variables being set
• Containers There are many functions that manipulate container • conPeek: Returns the value being held in a specific position in the
container.• conDel: Removes a value from a specific position in the container.• conNull: Returns an empty container.• conFind: Finds the position in the container that a certain value is
being held (if found). • conIns: Inserts a value into a specific position in the container. • conPoke: Replaces the value in a specific position in the container
with a new value. • conLen: Returns the number of elements in the container.
X++ CONTROL STATEMENTS(Contd.)
Operators:a) Assignment operators
Operator Term Description
= Becomes equal to
Assigns the expression on the right of the equal sign to the variable on the left.
+= Increments the variable on the left by the value on the right.
++ Increments the variable on the left by 1.
-= Decrements the variable on the left by the value on the right.
-- Decrements the variable on the left by 1.
X++ CONTROL STATEMENTS(Contd.)
Operators:b) Arithmetic operators
X++ CONTROL STATEMENTS(Contd.)
Operators:c) Relational operators
X++ CONTROL STATEMENTS(Contd.)
Operator Precedence:
X++ CONTROL STATEMENTS(Contd.)
Conditional Statementsa) If Statement
Code syntex is just like c#, c++if (condition) { //if true these statements are executed } else { //if false these statements are executed }
X++ CONTROL STATEMENTS(Contd.)
Conditional Statementsb) Switch statementswitch (expression) { case 'Choice1': Statement1; Statement2; break; case 'Choice2': Statement3; break; case 'Choice3': Statement4; Statement5; Statement6; break; default : DefaultStatement; }
X++ CONTROL STATEMENTS(Contd.)
Conditional Statementsc) Ternary Operator
condition ? statement1 : statement2;
X++ CONTROL STATEMENTS(Contd.)
Loopsa) while loop
while (condition) { //statement; }
X++ CONTROL STATEMENTS(Contd.)
Loopsb) Do...while statement
do { //statement; } while (condition);
X++ CONTROL STATEMENTS(Contd.)
Loopsc) For loop
for ( initial value ; condition ; increment) { //statement; }
X++ CONTROL STATEMENTS(Contd.)
Built-in functions: Built-in functions can be used anywhere in X++ code. These functions can be typed manually or accessed by using the context (right-click) menu in
the code editor and selecting List Built-in Functions, or by pressing Shift+F4. Examplestr letters; ; letters ="ABCDEFG"; print subStr(letters, 2, 4); print subStr(letters, 5, -3);Result : BCDE CDE
X++ CONTROL STATEMENTS(Contd.)
Communication Tools: Communicating with the end-user
Main types of communication are the following: Forms and reports which are used for input and output of larger
amounts of data Print commands, infologs and dialog boxes which are generally
used for specific data input and output
X++ CONTROL STATEMENTS(Contd.)
Communication Tools:The print command
print "This is a test message."; pause;
X++ CONTROL STATEMENTS(Contd.)
Communication Tools:Infolog
Infolog is the most common method of communicating to the user information about how a process has been executed.
Boxes can output a message to a user, but sometimes multiple messages are generated during processing.
Usage Example:Info ("This is an info infolog");
X++ CONTROL STATEMENTS(Contd.)
Communication Tools:Boxes Boxes display brief messages to application users. There are many different box types and each has their own box method. Methods in the box class take the following parameters
• The main text • The title bar text • Help text
Examplebox::info('Main Text', 'Title', 'This is the help text');
X++ CONTROL STATEMENTS(Contd.)
Communication Tools:DialogDialog boxes are a simplified type of form in Microsoft Dynamics AX.They are generated from the Dialog class.Example static void Simple_Dialog(Args _args) { dialog dlg; dialogGroup dlgGroup; dialogField dlgField; ; dlg = new dialog("Simple Dialog"); dlgGroup = dlg.addGroup("Customer"); dlgField = dlg.addField(TypeID(custAccount),"Account Number"); if (dlg.run()) { print dlgField.value(); pause; } }
CLASSES AND OBJECTS
A class is a software construct that defines the data (state) and methods (behavior) of the specific concrete objects that are subsequently constructed from that class.
How to create a Class1. Open the AOT. 2. Locate the Classes node. 3. Right-click the Classes node and select New Class in the context menu. The new class looks as shown below. 4. A new class named Class1 is created and contains one node: the classDeclaration node. It is empty by default. 5. Double-click the classDeclaration node. 6. Enter the declarations between the two { } braces. 7. Right-click on the class and select New Method. 8. Rename the method. 9. Type code between the two { } braces.
Method Access There are three modifiers available:
• Public allows the method to be called from any code in the application.
• Protected allows the method to be called only by methods in the same class or subclasses of the class in which the method is defined.
• Private allows the method to be called only by methods in the same class in which the method is defined.
CLASSES AND OBJECTS
Inheritance:Inheritance is a concept where one class can inherit all the methods
and variables from another class. A child class inherits the methods of the parent class. Syntax:class Child extends Parent { }
multiple inheritance is not support. Use interfaces and/or composition instead.
CLASSES AND OBJECTS
Method Types:a) Static Methods Static methods are methods that are attached to a class, but do not need that class
to be instantiated to execute that method. They are not within the scope of the class, so any class variables are not available in a static method.
static void myStaticMethod() { } myClass::myStaticMethod()
Main MethodIt is used by the system when the class is run directly from a menu item and it takes a parameter of type args.static void main(Args args){}Args is a class that is used to pass parameters between objects, for instance, various parameters can beset on the properties on a menu item.When the menu item calls a class, the args class containing those property values is passed to the main method using the args parameter.
Display MethodsDisplay methods are used on forms and in reports. Display methods return a value.display itemName itemName() {
inventTable inventTable ; select name from inventTable where inventTable.itemId == this.itemId; return inventTable.name;
}
CLASSES AND OBJECTS
Method Types:d) Accessor Accessor methods enable other elements to set or get the values
of variables in a class. It is common that they do both. str myName(str _myName = myName) { ; myName = _myName; return myName; }
CLASSES AND OBJECTS
Tables as Classes • A place for a table buffer is automatically assigned in a table
in classes the new method is used. • Fields in tables are public; they can be referred to from
everywhere. Fields in tables can be referred to directly; for example, in a report, whereas variables in a method can only
be referred to using access or methods.
ACCESSING THE DATABASE
In Dynamics Ax 2012
• Retrieve data from the database using a select statement Table Buffers: A table buffer is declared like a variable – the table name is specified
in the declaration. A table buffer stores complete records in a variable.Select Statements: Select statements are used to retrieve data from a database. The pure select statement returns records to a table buffer.
ACCESSING THE DATABASE (Contd.)
Select
static void Q1_Select1(Args _args){CustTable CustTable; ; select Address from CustTable; where CustTable.AccountNum == '1102'; print CustTable.Address; pause;}
// To Loop Records while select AccountNum, Name, Address from CustTable { print CustTable.AccountNum+ ": " + CustTable.Name + ": " + CustTable.Address; } pause;
SortYou can sort data retrieved from the database in many ways. This includes:
• Using existing indexes on the tables.• Using the order by clause in a select statement.• Using the group by clause in a select statement.
while select custTable index AccountIdx { print custTable.AccountNum, " ", custTable.currency; }
Inner joinwhile select ledgerTable join ledgerTrans where ledgerTrans.accountNum == ledgerTable.accountNum { amountMST += ledgerTrans.amountMST; }
Existwhile select AccountNum, Name from custTable order by AccountNum exists join * from ctr where (ctr.AccountNum == custTable.AccountNum)
notExistswhile select AccountNum, Name from custTable order by AccountNum notExists join * from ctr where (ctr.AccountNum == custTable.AccountNum)
outerwhile select AccountNum from custTable order by AccountNum outer join * from custBankAccount where custBankAccount.AccountNum == custTable.AccountNum { print custTable.AccountNum, " , ", custBankAccount.DlvMode; } pause;
CountCustTable xCT;int64 iCountRows; ;Select COUNT(RecID) from xCT;iCountRows = xCT.RecID;
ACCESSING THE DATABASE (Contd.)
Createstatic void Q13_Insert(Args _args){ CustTable CustTable; ; CustTable.AccountNum = "supposedAccount1"; CustTable.Name = "SupposedName1"; CustTable.insert(); info("Inserted");}
ACCESSING THE DATABASE (Contd.)
Update:static void Q14_Update(Args _args){ SalesTable SalesTable; ; ttsbegin; while select forupdate SalesTable where SalesTable.CustAccount == "1102" { SalesTable.SalesName = "aaaaa"; SalesTable.update(); info("Updated Successfully"); } ttscommit;}
SalesTable SalesTable; ; update_recordset SalesTable setting salesName = "Update RecordSet", DeliveryStreet = "New Address" where SalesTable.CustAccount == "1102 “; info("Updated Successfully via RecordSet");
ACCESSING THE DATABASE (Contd.)
Deletestatic void Q16_Delete(Args _args){ CustTable CustTable; ; ttsbegin; select forupdate CustTable where CustTable.AccountNum == "supposedAccount1";
CustTable.delete(); info("Deleted");
ttscommit;}
CustTable CustTable; ; while select forupdate CustTable where CustTable.AccountNum == "4018" delete_from CustTable where CustTable.AccountNum == "4018";
ACCESSING THE DATABASE (Contd.)
Transaction Integrity CheckingIt is important to ensure the integrity of all transactions within the
system. When a transaction begins, to ensure data consistency, it must finish completely with predictable results.
The following keywords help in integrity checking: • ttsbegin – Indicates the beginning of the transaction. • ttscommit – Indicates the successful end of a transaction. This
ensures the transaction performed as intended upon completion. • ttsabort – Used as an exception to abort and roll back a
transaction to the state before the ttsbegin.
ACCESSING THE DATABASE (Contd.)
Queries:A query is an application object in the AOTA query performs the same function as the select statements, but is a
better option as it allows for more flexible user interaction when defining which records are to be retrieved.
Queries Using X++:Queries can also be created and manipulated using X++. There are a
number of classes available that you can use to achieve this. Two important classes when executing a query are:
Query() The Query() class provides the framework for the query
QueryRun() QueryRun() class starts this framework dynamically.
ACCESSING THE DATABASE (Contd.)
Queries Using X++:static void Q20_ViaXPlusPlus(Args _args){ Query query; QueryBuildDataSource qbds; QueryBuildRange qbr; QueryRun queryrun; CustTable CustTable; ; query = new Query(); qbds = query.addDataSource(TableNum(CustTable)); qbr = qbds.addRange(FieldNum(CustTable,AccountNum)); qbr.value('1101'); qbds.addSortField(FieldNum(CustTable,AccountNum)); queryrun = new QueryRun(query); while(queryrun.next()) { CustTable = queryrun.get(TableNum(CustTable)); Print CustTable.AccountNum + ": " + CustTable.Name; } Pause;}
ACCESSING THE DATABASE (Contd.)
Accessing data from Different Companies:
static void Q10_CrossCompanies1(Args _args){ Container ConComapnies = ['cee','ceu']; CustTable CustTable; ; while select crossCompany : ConComapnies CustTable { Print CustTable.Name; } pause;}
EXCEPTION HANDLING
Exception:When code is running, errors can occur due to user input, setup,
data, code, or installation problems.Users need a clear indication of when errors occur so they can
resolve the problem or report it to an administrator or systems developer, who can investigate what went wrong.
EXCEPTION HANDLING
Exception Example:
static void Exception3(Args _args){ CustTable custTable; ; try { custTable.AccountNum = '54299'; custTable.CustGroup = '50'; custTable.Address = 'Lahore Pakistan'; if(!custTable.validateWrite()) throw error("1. Record Failed during Validation."); custTable.insert(); info("2. Record saved in database successfully, while passing validation"); } catch(Exception::Error) { error("3. There was an error, while inserting the record."); }}
Questions