Top Banner
My Collection This document is provided "as-is". Information and views expressed in this document, including URL and other Internet Web site references, may change without notice. This document does not provide you with any legal rights to any intellectual property in any Microsoft product or product name. You may copy and use this document for your internal, reference purposes. You may modify this document for your internal, reference purposes.
87

Query and Classes and Methods in AX 2012

Dec 25, 2015

Download

Documents

osamaanjum

Notes on AX 2012
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Query and Classes and Methods in AX 2012

My Collection

This document is provided "as-is". Information and views expressed in this document, including URL and other Internet Web site references, may change without notice. This document does not provide you with any legal rights to any intellectual property in any Microsoft product or product name. You may copy and use this document for your internal, reference purposes. You may modify this document for your internal,

reference purposes.

Page 2: Query and Classes and Methods in AX 2012

Table of ContentsChapter 1Classes and Methods

Queries in the AOT for Data Access

true

Page 3: Query and Classes and Methods in AX 2012

Classes and Methods [AX 2012]

Updated: March 11, 2011

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

This section contains topics about types in the X++ language.

Classes in X++

Methods in X++

Interfaces Overview

Microsoft Dynamics AX Class Overview

See also

Microsoft Dynamics AX Design Patterns

X++ Language Programming Guide

true

Page 4: Query and Classes and Methods in AX 2012

Classes in X++ [AX 2012]

Updated: September 28, 2011

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

A class is a software construct that defines the data and methods of the specific concrete objects that are subsequently constructed from that

class. The data represents the state of the object. The methods represent the behavior of the object.

Variables are the data for the class. Variables in an X++ class are specific to objects that are constructed from that class. Every object

constructed from the class declaration has its own copy of the variables. Such variables are known as instance variables. You cannot declare

static variables in X++.

Methods are the sequences of statements that operate on the data. Methods are typically declared to operate on the instance variables of the class,

and are known as instance methods or object methods. In X++ you can also declare static methods.

In This Section

Declaration of Classes

Constructors

Destructors

Creating a Subclass

Tables as Classes

See also

Methods in X++

Page 5: Query and Classes and Methods in AX 2012

Declaration of Classes [AX 2012]

Updated: June 20, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

You create application classes by using the Application Object Tree (AOT).

Creating a Class in the Application Object Tree

You create an application class by following these steps:

1. In the AOT, locate the Classes node.

2. Right-click the Classes node and click New Class in the shortcut menu.

3. Expand the Class1 node, so you can see the classDeclaration node.

4. Right-click the classDeclaration node, and then click View Code. This displays the code Editor window.

In the classDeclaration code block, before the open brace {, the class declaration is decorated with the public modifier. All classes in Microsoft

Dynamics AX are public. If you remove the public modifier, the system still treats the class as public.

Other modifiers can be specified on the class declaration, including final and extends.

Creating Variables in a Class

All classes are public, but all member variables are implicitly private. Even though all member variables are private, you cannot decorate a

member variable with the private keyword. All member variables belong only to object instances of the class. You cannot decorate a member

variable with the static keyword. The following steps exemplify these rules:

1. Right-click the classDeclaration node, and then click View Code.

2. In the code Editor window for the classDeclaration, add the following declaration of a string variable on a line between the open and

close braces {}:

str firstName;

The X++ code for the classDeclaration now looks like the following.

public class Class1

{

str firstName;

}

You can provide access to a member variable by returning it from a simple instance public methods that get and set its value.

For information about how to write variable declarations, see Declaration of Variables.

Creating Accessor Methods in a Class

In this section you add simple public methods that get and set the value of the member variable firstName.

Page 6: Query and Classes and Methods in AX 2012

Add a Getter Accessor Method

Follow these steps to add a method that gets or returns the value of a member variable:

1. Right-click the Class1 node, and then click New > Method.

2. Rename the method1 node to getFirstName.

3. In the code Editor window, paste in the following X++ code for the method.

public str getFirstName()

{

return firstName;

}

Note

The this keyword cannot be used to reference member variables such as firstName.

Add a Setter Accessor Method

Follow these steps to add a method that sets the value of a member variable:

1. Right-click the Class1 node, and then click New > Method.

2. Rename the method1 node to setFirstName.

3. In the code Editor window, paste in the following X++ code for the method.

public void setFirstName(str _firstName)

{

firstName = _firstName;

}

Test the Accessor Methods

The following X++ job tests the preceding getter and setter accessor methods. static void AccessorJob61(Args _args)

{

Class1 c1;

c1 = new Class1(); // ‘new’ method is inherited from the Object class.

c1.setFirstName("Isaac");

print c1.getFirstName();

pause;

/*** Content of the Print window:

Isaac

***/

}

See also

Best Practices for Class Declarations

Creating a Subclass

Page 7: Query and Classes and Methods in AX 2012

Constructors [AX 2012]

Updated: November 30, 2011

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

To create an instance of a class (an object), you have to instantiate it. The default constructor is the new method:

// Declares a variable to refer to a Point object

Point myPoint;

;

// Allocates an instance of a Point object

myPoint = new Point();

It is a best practice to make the new method protected, and instead, use a static construct method, or static new method as the public constructor

for the class. If no initialization is required, use a static construct method, otherwise use a static new method. For more information, see Best

Practices for Constructors.

Creating Other Objects from a Constructor

A class constructor can instantiate other objects, in addition to creating an instance of the class. The following code illustrates one such situation

by declaring a Rectangle class that uses two Point objects to define its bounds.

class Rectangle

{

Point lowerLeft;

Point upperRight;

}

new(real _topLeftX, real _topLeftY, real _bottomRightX, real _bottomRightY)

{

lowerLeft = new Point(_topLeftX, _topLeftY);

upperRight = new Point(_bottomRightX, _bottomRightY);

}

Accessing Members in a Object

X++ does not allow you to access the variables of an object by referring to the names of the variables, qualified with the name of the object:

Page 8: Query and Classes and Methods in AX 2012

myPoint.x = 10.0; //Not possible

myPoint.y = 25.7; //Not possible

The only way to access the member variables in a class is through accessor methods. For information about accessor methods, see Accessor

Methods.

See also

Destructors

Destructors [AX 2012]

Updated: October 11, 2008

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

A destructor is used to explicitly destroy a class object.

X++ objects are destructed automatically when there are no more references to them. You can destruct them explicitly in the following ways:

Use the finalize method.

Set the object handle to null.

finalize

Use the finalize method to explicitly destruct an object. There are no implicit calls to the finalize method. You must call it to execute the

statements in it.

// From any method in a class.

{

...

if(Condition)

// Removes object from memory.

this.finalize();

...

}

The finalize method is also where to put any other clean-up code. For example, if your class uses a DLL module, you can use the finalize method

to release the DLL when you no longer need it.

Page 9: Query and Classes and Methods in AX 2012

Caution

Use finalize carefully. It will destruct an object even if there are references to it.

Set an Object Handle to null

Set the object handle to null to terminate an object. This only destroys the object if there are no other object handles pointing to it. Check that

other programmers haven't already used the object handle.

For example:

// Create an object handle of the type MyObject.

MyObject mo;

;

// Create an object of MyObject type and

// link it to the object handle.

mo = new myObject();

// Terminate the object.

mo = null;

See also

Constructors

Declaration of Classes

Declaration of Methods

Creating a Subclass [AX 2012]

Updated: November 15, 2013

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

Subclasses are classes that extend (inherit from) other classes. In X++, a new class can only extend one other class; multiple inheritance is not

supported. If you extend a class, it inherits all the methods and variables in the parent class (the superclass).

Subclasses enable you to reuse existing code for a more specific purpose, saving time on design, development, and testing. To customize the

behavior of the superclass, override the methods in your subclass.

For terminology, a superclass is often called a base class, and a subclass is often called a derived class.

For more information about overriding a method, see Overriding a Method.

Example

The following example creates a class called Point and extends it to create a new class called ThreePoint.

class Point

{

// Instance fields.

real x;

real y;

true

Page 10: Query and Classes and Methods in AX 2012

;

// Constructor to initialize fields x and y.

new(real _x, real _y)

{

x = _x;

y = _y;

}

}

class ThreePoint extends Point

{

// Additional instance fields z. Fields x and y are inherited.

real z;

;

// Constructor is overridden to initialize z.

new(real _x, real _y, real _z)

{

// Initialize the fields.

super(_x, _y);

z = _z;

}

}

Preventing Class Extension

You can prevent classes from being extended by using the final modifier:

public final class Attribute 

 { 

     int objectField; 

 }

See also

Table Inheritance Overview

Classes in X++

Tables as Classes [AX 2012]

Updated: September 30, 2011

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

Application tables can be viewed as being similar to application classes in Microsoft Dynamics AX, but with the following differences from

classes:

Tables are persistent.

Table fields are always public.

A table in the AOT almost always corresponds to a real object.

The definition of a table must sometimes be erased if you later want another table to extend it.

See also

Page 11: Query and Classes and Methods in AX 2012

Table Inheritance Overview

Classes in X++

Methods in X++ [AX 2012]

Updated: March 7, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

The following blocks of code are standard for X++ application classes:

Code block type Description

classDescription declaration Contains class modifiers such as public, private, and extends.

true

Page 12: Query and Classes and Methods in AX 2012

block Also contains the field members for objects that are constructed from this class. IntelliSense can display a list of the members when you type the

X++ keyword this.

new method The constructor. This method can be called only by using the new keyword. The syntax is typically similar to:

 myClassInstance = new MyClass();

Derived classes can call the new method of their constructor by calling super method reference.

finalize method The destructor method.

However, in X++ this is a destructor only by convention. The finalize method is not called automatically by the system during garbage

collection.

Additional methods for a class fall into the following types:

Instance methods

Static methods

Main methods

Note

Methods can be created on many kinds of items in the AOT other than just classes. The list includes the following:

Maps

Views

Data Sets

Forms

Queries

Instance Methods

Instance methods, or object methods, are embedded in each object that is created from the class. They are called by using the following syntax:

objectHandleName.methodName();

You must instantiate the object before you can use the method.

Caution

If you later convert an instance method to a static method, you must restart the Microsoft Dynamics AX client for the compiler to note the change. Once you have converted the

instance method to a static method, you can no longer call this method from the instance of the class -- only the class itself. Static methods are discussed in the next section.

Static Methods

Static methods, or class methods, belong to a class and are created by using the keyword static. They are called by using the following syntax:

ClassName::methodName();

You do not need to instantiate an object before you use static methods. Static methods are widely used in Microsoft Dynamics AX to work with

data that is stored in tables.

Note

It is not possible to use member variables in a static method.

For more information, see Static Methods.

Main Methods

Page 13: Query and Classes and Methods in AX 2012

A main method is a class method that is executed directly from a menu option.

static void main (Args _args) 

 { 

     // Your X++ code here. 

 }

The method should only create an instance of the object and then call the necessary member methods. The _args parameter allows you to transfer

data to the method.

For more information, see Activating a class from a menu item.

See also

Declaration of Methods

Method Modifiers

Overriding a Method

Best Practices for Methods

Table Methods

Declaration of Methods [AX 2012]

Updated: October 5, 2011

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

Page 14: Query and Classes and Methods in AX 2012

Methods are created using the Application Object Tree (AOT). When methods are created, MorphX creates a default declaration that must be

altered.

Method declarations consist of a header and a body. The method header declares the name and return type (possibly void) of the method, the

method modifiers, and parameters. The method body consists of variable declarations, method declarations, and statements.

Return Type

If a method does not return anything, you must specify this with the void keyword.

void methodName()

{

    ...

}

If a method returns something, you must specify the return type and include a return statement.

int methodName()

{

    return myInt;

}

Syntax

Method declaration = Heading  Body

Heading = [ Modifiers ]  ReturnType  MethodName  (  ParameterList  )

Modifiers = [client] [server] [edit | display | public | protected | private] [static | abstract | final ]

ReturnType = Datatype  | void | anytype

MethodName = Identifier

ParameterList = [ Parameter  { ,  Parameter  }]

Parameter = Datatype  Variableidentifier  [ =  Expression  ]

Body = { [  VariableDeclarations  ] [  EmbeddedFunctionDeclarations  ] [  Statements  ] }

EmbeddedFunctionDeclaration = Heading  {[  VariableDeclarations  ] [  Statements  ]}

Note

If you use the anytype return type, the method can return any data type.

Examples

Method Without a Return Type

Page 15: Query and Classes and Methods in AX 2012

void update ()

{

// Variable declared and initialized

CustTable this_Orig = this.orig();

// First statement in body (begin transaction)

ttsBegin;

this.setNameAlias();

// Calls super's implementation of update

super();

this.setAccountOnVend(this_Orig);

if (this_Orig.custGroup != this.custGroup)

ForecastSales::setCustGroupId(

this.accountNum,

this_Orig.custGroup,

this.custGroup);

// Commits transaction

ttsCommit;

}

Method with Parameters

boolean checkAccountBlocked(AmountCur amountCur)

{

if (this.blocked == CustVendorBlocked::All

||(this.blocked == CustVendorBlocked::Invoice

&& amountCur > 0 ))

return checkFailed(strFmt("@SYS7987",this.accountNum));

return true;

}

checkAccountBlocked returns a Boolean value and acts on the parameter amountCur.

Methods with Modifiers

Only the method headers are shown in the following examples.

// A method that cannot be overridden

final int dontAlterMe()

// A static method

static void noChange()

// A display method that returns an integer

display int value()

See also

Method Modifiers

Using Optional Parameters

true

Page 16: Query and Classes and Methods in AX 2012

Method Modifiers [AX 2012]

Updated: October 6, 2011

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

There are several modifiers that can be applied to method declarations. Some of the modifiers can be combined (for example, final static).

The following table describes the method modifier keywords of the X++ language.

Modifier Description

abstract The method is declared but not implemented in a parent class. The method must be overridden in subclasses.

If you try to create an object from a subclass where one or more of the abstract methods belonging to the parent class have not been overridden, you will get a compiler

error.

Note

Classes can also be abstract. Sometimes a class represents an abstract concept, but it should not be instantiated: Only subclasses should be instantiated. Such base classes can be declared abstract. Consider the case where the programmer wants to model the concept of an account. Accounts are abstract—only derived classes (ledger accounts and so on) exist in the real world. This would be a clear case for declaring the Account class abstract.

client Establishes the location where the method is to be executed (on the client).

Can only be used on static methods. If the method is not static, specify the location by using the class property RunOn.

display Indicates that the method's return value is to be displayed on a form or a report. The value cannot be altered in the form or report.

The return value is typically a calculated value, for example, a sum.

For more information about the display and edit modifiers, see Using the display Method Modifier.

edit Indicates that the method's return type is to be used to provide information for a field that is used in a form. The value in the field can be edited.

final Indicates that the method cannot be overridden in any class that derives from its class.

public Methods that are declared as public are accessible anywhere the class is accessible and can be overridden by subclasses. Methods that have no access modifier are

implicitly public.

protected Methods that are declared as protected can only be called from methods in the class and in subclasses that extend the class where the method is declared.

private Methods that are declared as private can be called only from methods in the class where the private method is declared.

server Establishes the location where the method is to be executed (on the server).

Can only be used on static methods. If the method is not static, you need to specify the location using the class property RunOn.

static Specifies that the method is a class method and does not operate on an object.

static methods cannot refer to instance variables and are invoked by using the class name rather than on an instance of the class (MyClass::aStaticProcedure()).

For more information, see Static Methods.

Page 17: Query and Classes and Methods in AX 2012

Static Methods [AX 2012]

Updated: October 25, 2011

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

In X++ you can decorate a method with the static keyword. This keyword instructs the system to create only one instance of the method

regardless of how many instances of its class you create. This single instance is used throughout your Microsoft Dynamics AX session.

Static methods are generally intended for cases where the following criteria are met:

The method has no reason to access the member variables that are declared in the classDeclaration block of the class.

The method has no reason to call any instance (non-static) methods of the class.

Syntax

Declaring a Static Method

Consider the example of a software key type that is used for piracy prevention. Each instance of a software key can have its own unique value.

But all software keys must conform to the rules of software key design. Therefore the logic to test for software key conformance is the same for

all software keys. The method that contains the conformance validation logic should be static. Here is an example of a method that is declared

with the static keyword:

static public boolean validateSoftwareKey(str _softwareKeyString) 

 { 

     // X++ code here. 

 }

Calling a Static Method

In the following example, there is no need to first construct an instance of the SoftwareKey class before you call a static method on the class. To

call the static method validateSoftwareKey, the syntax starts with the name of the class that contains the method. A pair of colon (::) characters is

used to connect the class name to the static method name.

boolean yourBool = SoftwareKey::validateSoftwareKey(yourSoftwareKeyString);

See also

Declaration of Methods

Method Modifiers

Best Practices for Method Modifiers

Methods in X++

Page 18: Query and Classes and Methods in AX 2012

Method Access Control [AX 2012]

Updated: July 20, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

In X++, you use the accessor keywords public, protected, and private to control whether the methods in other classes can call the methods on

your class. The accessor keywords on methods also interact with the rules for class inheritance. The following table describes the accessor

keywords you use with methods.

public Methods that are declared as public can be called from anywhere the class is accessible. In addition, a public method can be overridden by a subclass, unless the

method is declared as final.

protected Methods that are declared as protected can be called only from the following:

From methods in the class.

From methods in a subclass of the class that contains the protected method.

Methods that are protected can be overridden in subclasses.

private Methods that are declared as private can be called only from methods in the class where the private method is declared. No private method can be overridden in a

subclass.

When you create a new method, the default accessor keyword that appears in the code editor is private. This is the most conservative default for maximum security.

Note

In the Application Object Tree (AOT), all classes under AOT > Classes are public. Explicit use of the public keyword is recommended in the classDeclaration code block for each

class, but the class is public even if the public keyword is omitted.

Static and Instance Methods

The accessor keywords on methods never restrict call between two methods that are in the same class. This is true regardless of which of the two

methods are static or non-static.

In a static method, calls to the new constructor method are valid even if the new constructor method is decorated with the private modifier. The

syntax for these calls requires the use of the new keyword of X++. The code in a static method must construct an instance object of its own class

before the code can call any instance methods on the class.

Increase Access When Overriding

When a method is overridden in a subclass, the overriding method must be at least as accessible as the overridden method. For example, the

following X++ compiler rules apply to overriding a protected method in a subclass:

A public method in a superclass can be overridden only by a public method in the subclass.

Page 19: Query and Classes and Methods in AX 2012

In a subclass, a public method or a protected method can override a protected method of the superclass.

In a subclass, a private method cannot override a protected method of the superclass.

Design Pattern of private new

All application classes are under AOT > Classes. Every application class has the constructor method named new, even if the class has no new

node in the AOT. If the class has no explicit new node, the implicit new method is public.

A design pattern that is sometimes used in Microsoft Dynamics AX is to declare the explicit new constructor method as private. Then a public

static method is added to call the new method. The static method can restrict or control the call the new method based on various conditions, if

necessary.

See also

Method Modifiers

Declaration of Methods

Using Optional Parameters [AX 2012]

Updated: June 20, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

It is possible to initialize parameters in the method declaration. This makes the parameter an optional parameter. If no value is supplied in the

method call, the default value is used.

Code Example 1: Function used as the Default

The following methods are considered to be members of the MyClass1 class, which includes the field member birthDate.

public class MyClass1 // classDeclaration

{

date birthDate;

}

Next, the class contains a constructor that takes a date type as a parameter. That value is assigned to the field member birthDate.

void new(date _date)

{

birthDate = _date;

}

Next is the CalculateAgeAsOfDate method, for which the following are true:

The method references the birthDate field.

The method has an optional parameter. In this example, the default value is the return value of a function.

The method is called by the Main method.

public real CalculateAgeAsOfDate // X++

( date _calcToDate = today() ) // Parameter is optional for callers.

{

return (_calcToDate - birthDate) / 365;

}

Next is the Main method which calls the CalculateAgeAsOfDate method twice.

static public void Main(Args _args)

{

Page 20: Query and Classes and Methods in AX 2012

MyClass1 mc = new MyClass1(13\5\2010); // birthDate is initialized.

// Optional parameter's default is used.

print "Age in years: " + num2str(mc.CalculateAgeAsOfDate(),2,0,0,0);

// January 2, 2044 is the parameter value for _date.

print "Age in years: " + num2str(mc.CalculateAgeAsOfDate(2\1\2044),2,0,0,0);

pause;

}

Code Example 2: Invalid Sequence of Parameters

All required parameters must be listed before the first optional parameter. In the following invalid example, the required parameter _i3 is listed

after the optional parameter _i2.

static public int AddThreeIntsA // Invalid X++, does not compile.

(int _i1,

int _i2 = 3,

int _i3) // Required parameter cannot follow an optional parameter.

{

return _i1 + _i2 + _i3;

}

Code Example 3: Cannot Skip to Second Optional Parameter

When calling a method, the caller cannot override the default value of the final optional parameter unless the caller also overrides the default

values of every other optional parameter.

In the following example, the first method has two optional parameters. The second method is a caller of the first method. The caller wants to

override only the _i3 default value, but the compiler requires that all prior optional parameters also be overridden in the call.

static public int AddThreeIntsB

(int _i1,

int _i2 = 2,

int _i3 = 3)

{

return _i1 + _i2 + _i3;

}

Next, the second method has a commented section showing the failed attempt to accept the default of the first optional parameter _i2 while

trying to override the final optional parameter _i3.

static public void Main(Args _args)

{

// No way to skip the first optional parameter (so it can default)

// while also specifying the value of the second optional parameter.

//

//print MyClass1::AddThreeIntsB(1, , 99); // Would fail to compile in X++.

// Settle for overriding both optional parameters.

//

print MyClass1::AddThreeIntsB(1, 2, 99);

pause;

}

See also

Declaration of Methods

Page 21: Query and Classes and Methods in AX 2012

Accessor Methods [AX 2012]

Updated: August 6, 2011

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

If an object uses another object to do some work on its behalf, the first object sends a message to the second object. In response, the second

object invokes the selected method.

This programming technique is one of the best ways to create models and simulations of complex real-world systems. The following example

defines a Point class so that it uses accessor methods to access the variables x and y.

class Point

{

// Instance variables

real x;

real y;

//Constructor to initialize to a specific or default value

void new(real _x=10, real _y=10)

{

x = _x;

y = _y;

}

//Accessor method

void setX(real _x)

{

x = _x;

}

//Accessor method

void setY(real _y)

{

y = _y;

}

//Accessor method

real getX()

Page 22: Query and Classes and Methods in AX 2012

{

return x;

}

//Accessor method

real getY()

{

return y;

}

}

These method declarations illustrate how the Point class provides access to its variables from the outside world. Other objects can manipulate the

instance variables of Point objects by using the accessor methods:

//Declare a variable to refer to a Point object

Point myPoint;

//Create a Point object

myPoint = new Point();

//Set the x variable using the accessor method

myPoint.setX(10.0);

//Set the y variable by means of the accessor method

myPoint.setY(25.7);

By hiding details of the internal implementation of a class, X++ allows the programmer to change the implementation of the class in the future

without breaking any code that uses that class.

Note

The X++ callstack depth is limited to 100.

See also

Methods in X++

Page 23: Query and Classes and Methods in AX 2012

Overriding a Method [AX 2012]

Updated: February 20, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

The methods in a class are inherited by any class that extends it. You can alter the functionality of an inherited method by creating a method in

the subclass with the same name and parameters as in the superclass. This is called overriding the method. For example:

// Superclass: Attribute

public class Attribute

{

    int objectVariable;

}

void methodAtt()

{

    //Some statements

}

// Subclass: ColorAttribute

public class ColorAttribute extends Attribute

{

    int addedObjectVariable;

}

void methodAtt()

{

    //Some statements

}

ColorAttribute is a subclass of Attribute and therefore inherits the method methodAttr. However, because ColorAttribute defines a method with

the same name and the same number of arguments, the method in the superclass is overridden.

Preventing Method Overriding

Page 24: Query and Classes and Methods in AX 2012

Static methods cannot be overridden because they exist per class. To protect other sensitive methods, or core methods, from being overridden,

use the final modifier. In the example below, methodAtt is declared as final, and so it cannot be overridden in any class that extends Attribute.

public class Attribute

{

    int objectVariable;

}

final void methodAtt()

{

    //Some statements

}

Note

You should not specify new or finalize methods as final.

For more information about inheritance in X++, see Creating a Subclass.

Overriding vs. Overloading

Overloading is where there is more than one method with the same name, but the methods have different signatures (return type or parameter

lists or both). Overriding is where the superclass's implementation of a method is altered by the subclass's implementation of the method, but the

signatures of both methods are the same.

X++ supports overriding, but it does not support overloading.

Difference between method overriding and overloading

Overriding is the concept of having functions of same name and signature in different classes. one in the super class can be made virtual and

other can override the functionality of virtual one. Overloading is the concept of having functions of same name, but different signature in same

class. They are differentiated by the compiler by their signatures.

Overloading methods

1. They appear in the same class or a subclass

2. They have the same name but, have different parameter lists, and can have different return types.

Overriding methods

It allows a subclass to re-define a method it inherits from it's superclass overriding methods:

1. It appears in subclasses

2. They have the same name as a superclass method

3. They have the same parameter list as a superclass method

4. They have the same return type as as a superclass method

5. They have the access modifier for the overriding method may not be more restrictive than the access modifier of the superclass method

Page 25: Query and Classes and Methods in AX 2012

Parameters and Scoping [AX 2012]

Updated: October 11, 2008

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

The scope rules in X++ state that all methods have their own scope. To use data from one scope in a different scope, you have to transfer the

data from one scope into the other scope by using parameters.

A method can take one or more parameters. Within the scope of the method, these parameters are treated like local variables and are initialized

with the value from the parameter in the method-call. The following table shows an example.

Class declaration Method methodQ

class Parameter void methodQ(int aval, real bval)

{ {

    int a;     a = aval;

    real b;     b = bval;

} }

Here, a class called Parameter is declared. The class has a method (methodQ), which takes two parameters: an integer and a real. Four variables

are visible within the scope of methodQ: aval, bval, a, and b. The a and b variables are in the scope because they are defined in the class

declaration for the class.

Page 26: Query and Classes and Methods in AX 2012

ssume that ParameterObject is an instance of the Parameter class. If methodQ is invoked on ParameterObject,

ParameterObject.methodQ(1,2.0);

aval is set to the value 1 within the method and the variable bval is set to 2.0 (it is a real) within the method. The two variables a and b in the

ParameterObject are set to 1 and 2.0, respectively. You can pass the value of any expression as a parameter.

Parameters Are Passed by Value

All parameters are passed by value. You cannot change the value of the original variable—you can change only the local variable in the method,

which is a copy of the original. The following table shows an example.

Class declaration Method methodA Method methodB

class ByValue void methodA(int i) void methodB()

{ { {

}     i = i + 1;     int i = 3;

    print i;     print i;

}     this.methodA(i);

    print i;

}

Here, a class ByValue is declared with two methods: methodA and methodB.

methodB has a local variable named i, which is used as a parameter to a call methodA.

methodA uses a parameter called i and therefore has a local variable called i. This local variable has the value of the variable i in methodB

(because it is used as a parameter in the call).

The result of invoking methodB is that the value of i is printed with its initial value in methodB (3), and then i is passed into methodA as a

parameter and printed again with its new value (4). Finally, i is printed again with the value from methodB (3). This illustrates that the two i

variables are two different variables.

true

Page 27: Query and Classes and Methods in AX 2012

Scope of Variables in Methods [AX 2012]

Updated: January 28, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

A scope defines the area in which an item can be accessed. Variables defined in a class are available to the methods within that class. Variables

in methods can be accessed only within the current block, as shown in the following figure.

The class A contains methods b and c and class variables. All methods in the class can see and use all variables in the class.

The method b has some local variables that can only be accessed from within method b.

Method c has some local variables, a function d, and a function e. Functions d and e can be seen only inside method c. As functions d and e are

declared inside method c, they have access to their local variables—the local variables in c and the variables in the class, respectively.

Page 28: Query and Classes and Methods in AX 2012

See also

Parameters and Scoping

Variable Scopes

Local Functions [AX 2012]

Updated: July 20, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

You can declare local functions inside a method or a job in X++. A local function can contain code that would otherwise have to be duplicated in

two or more places within your method.

Tip

The best practice is to add private methods to the class rather than to add local functions inside the method.

Code Example of a Local Function

The following X++ job code example shows valid declarations of two local functions named localFunc55b and localFunc66c. Calls to the local

functions occur after the function declarations in the code example, as is required.

static void G_LocalFuncJob2(Args _args) // X++ job.

{

int nn = 654;

Page 29: Query and Classes and Methods in AX 2012

void localFunc55b(int _iNum) // The local function.

{

str sInnerString;

sInnerString = "String_in_localFunc55b";

info(strFmt("localFunc55b: %1 , %2 , %3",

_iNum, sInnerString, nn));

}

void localFunc66c()

{

info("Printing from inside localFunc66c.");

}

; // This semicolon marks the end of local function declarations.

localFunc55b(55);

localFunc66c();

// Next print statement would fail to compile,

// because sInnerString is restricted to the

// scope of the local function in which it is declared.

//print sInnerString; pause;

}

/*** Infolog window display:

Message (07:38:54 pm)

localFunc55b: 55 , String_in_localFunc55b , 654

Printing from inside localFunc66c.

***/

Declaration of Local Functions

The local functions must be declared physically above any non-declaration statements that exist in the method or job.

You can declare more than one local function in your method. But all local functions must be declared in an uninterrupted series, with

the set terminated by one semicolon.

Scoping of Variables

Code that is inside the local function can access variables that are declared in the method or job that contains the local function.

Code that is outside the local function cannot access variables that are declared in the local function.

Calls to Local Functions

A local function can be called only by code in the same method or job where the local function is declared.

An X++ local function should never call itself. Such recursion can prevent the successful compile of X++ to .NET Framework CIL.

Note

X++ local functions are transformed into inline code when the X++ method is compiled into CIL.

See also

Methods in X++

Best Practices for Local Functions

Page 30: Query and Classes and Methods in AX 2012

Server/Client Location of Methods [AX 2012]

Updated: February 22, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

The table below describes what the default client/server location is for different kinds of methods, and whether this default behavior can be

changed.

Default behavior Can be

changed

Page 31: Query and Classes and Methods in AX 2012

Class Static Methods Run in the same location as that designated by the RunOn property for the class. Yes

Class Instance

Methods

Run in the same location as the class object. The location of instances of the class is determined by the RunOn property for the class. No

Table Static Methods Run where they are called from (RunOn property is Called from). Yes

Table Instance

Methods

Run where they are called from (RunOn property is Called from).

The standard table methods insert, doInsert, update, doUpdate, delete, and doDelete on the Server (where the data source is). This

cannot be changed.

Yes

The this Object [AX 2012]

Updated: December 6, 2011

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

In an X++ method, the keyword this is a reference to the instance of the class or table in which the this keyword is used. The this reference is

never required, but it can clarify your code, and it enhances the behavior of IntelliSense in the code editor.

The this reference can be used in the following ways:

Page 32: Query and Classes and Methods in AX 2012

Can be used to qualify the names of other instance (non-static) methods in the same class where the this reference is used. For

example:

 boolColorChanged = this.colorItOrange();

Note

In X++ all calls to instance methods must be qualified, either with the this reference or with a variable.

In contrast, C# does not always require such qualification.

Can be used to quality the names of methods that are inherited by the this object.

Can be used to qualify the names of fields on the table that contains the method that the this keyword is used in.

The this reference cannot be used in the following ways:

Cannot be used to qualify the names of member variables that are declared in the classDeclaration code.

C# allows such qualification.

Cannot be used in a static method.

Cannot be used to qualify the names of static methods of the class or table.

See also

Methods in X++

Interfaces Overview [AX 2012]

Updated: November 22, 2013

Page 33: Query and Classes and Methods in AX 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

In X++ an interface is a specification for a set of public instance methods. To create an interface, you begin by using the AOT to create a class.

You edit the code of its classDeclaration node to replace the keyword class with the keyword interface. Then you add methods to the interface

just as you would for a class, except no code is allowed inside the method bodies.

The purpose of interfaces is to define and enforce similarities between unrelated classes without having to artificially derive one class from the

other.

Implements and extends 

You can add the implements keyword on a class declaration, and this requires the class to declare the methods that are specified by the interface.

A class declaration can implement multiple interfaces by listing them after the single occurrence of the implements keyword, with commas

separating the interface names.

An interface can extend another interface by using the extends keyword. An interface cannot extend more than one interface.

Public 

All interfaces are public regardless of whether you explicitly write the keyword public in front of the keyword interface in the classDeclaration.

The methods on an interface are also public, and again the explicit inclusion of the keyword public is optional.

All interface methods that a class implements must be declared with the explicit keyword public in the class. Also, a class that implements an

interface must also be declared with public.

Related Code Examples

This section shows the code for an imaginary Automobile class that implements two interfaces. The classDeclaration code for the class is shown,

as is the classDeclaration for one of the interfaces. Also, the code for the getSpeed method is shown for the class and the interface.

IDrivable Interface

First is the classDeclaration for the interface IDrivable.

classDeclaration for interface IDrivable

Next is the specification that the interface IDrivable has for the getSpeed method.

getSpeed method specification on IDrivable

Automobile Class

Now we examine the code in the Automobile class that implements the IDrivable interface.

Page 34: Query and Classes and Methods in AX 2012

classDeclaration for Automobile, include the implements keyword

Finally we examine the full implementation of the getSpeed method on the Automobile class. The method contains X++ in its body between the

{}.

getSpeed method implementation

'is' Keyword Works for Interfaces

The following code example demonstrates that the keyword is does work for a class that implements an interface.

static public void Main(Args _args) // X++

{

IDrivable yourIDrivable;

Automobile myAutomobile;

str sTemp = "'is' keyword does Not work for interfaces.";

myAutomobile = new Automobile();

if (myAutomobile is IDrivable)

{

yourIDrivable = myAutomobile;

yourIDrivable.setSpeed(42);

sTemp = int2str(yourIDrivable.getSpeed());

}

Global::info(sTemp);

return;

}

/*** Output to Infolog:

Message (06:46:33 pm)

42

***/

The keyword is also works for a class that extends another class.

Page 35: Query and Classes and Methods in AX 2012

Microsoft Dynamics AX Class Overview [AX 2012]

Updated: September 27, 2011

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

There are two main kinds of classes in Microsoft Dynamics AX:

Application classes are implemented in X++. They are available in the Classes node in the AOT.

System classes, sometimes called kernel classes, are implemented in C++. They are listed under the System Documentation >

Classes node in the AOT. However, the source code for these classes is not available.

In This Section

Substitute Application Classes for System Classes

Execute Startup Commands

Batch Processing Classes

Image Manipulation Classes

Query Object Model

System Classes Overview

Performing Reflection with the TreeNode Class

Performing File IO with the TextIo Class

See also

System Classes Overview

Classes and Methods

Page 36: Query and Classes and Methods in AX 2012

Substitute Application Classes for System Classes [AX 2012]

Updated: September 29, 2011

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

You should call the substitute application classes instead of calling the system classes that they extend.

In the Application Object Tree (AOT) under System Documentation > Classes there are several kernel or system classes whose names begin

with a lowercase x. Examples of the x system classes include xApplication and xVersionControl. Some of the x system classes are extended by

X++ application classes which are under AOT > Classes. For example, the Application X++ class extends the xApplication system class.

The X++ classes that derive from the x system classes are called substitute application classes. In the AOT under the Classes node, the icon next

to the substitute application classes differs from the standard icon.

Special X++ Global Variables

Some of the substitute application classes that extend an x system class are associated with a special X++ global variable that represents an

instance of the X++ class. For example, the appl variable references a pre-instantiated object from the Application X++ class. The advantage of

the appl variable is that the system maintains the object throughout the scope of your session. It would be less efficient for your X++ code to

repeatedly use the new Application() syntax to obtain an instance of the Application X++ class.

You should not use the xApplication system class. Use the Application substitute application class instead. You can reference the static members

of the Application X++ class by using the standard syntax Application::checkForNewBatchJobs(). But you should reference the instance

members of the Application class by using its corresponding special system variable appl, if one exists. This pattern applies to most of the x

system classes. The Session substitute application class is one exception to this pattern, because there is no special system variable for Session.

The following table lists x system classes for which there is a corresponding substitute application class. The special X++ global variables are

also shown for those classes that have one.

Application class System class Global variable Runs on

Args xArgs (none) Client and server

Application xApplication appl Server

ClassFactory xClassFactory classFactory Client and server

Company xCompany appl.company Server

Global xGlobal (none) Client and server

Info xInfo Infolog Client

MenuFunction xMenuFunction (none) Client and server

Page 37: Query and Classes and Methods in AX 2012

Session xSession (none) Client and server

VersionControl xVersionControl versionControl Client

Example X++ Job that Uses Special Variables

The following X++ job demonstrates the syntax for using several special X++ variables that reference instances of the substitute application

classes.

static void UseSpecialSystemVariablesForXJob(Args _a)

{

TreeNode treeNode2;

Args args3;

FormRun formRun4;

// appl variable

print appl.buildNo();

// company variable

appl.company().reloadRights(); // referenced through appl

// Infolog variable

treeNode2 = infolog.findNode("\\forms\\custTable");

print treeNode2.AOTgetProperty("Name");

pause; // do want to continue

// classFactory variable

args3 = new Args(formstr(vendTable));

formRun4 = classFactory.formRunClass(args3);

formRun4.init();

formRun4.run();

formRun4.detach();

Global::info("Job is ending. This is a message in the Infolog.");

pause;

}

See also

Microsoft Dynamics AX Class Overview

Page 38: Query and Classes and Methods in AX 2012

Execute Startup Commands [AX 2012]

Updated: February 4, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

Use the SysStartupCmd class framework to execute commands at startup.

When Microsoft Dynamics AX starts, calls are made to the *startup methods on the application-substituted kernel classes Application

(Application.startup) and Info (Info.startup).

Caution

The *startup methods are used for vital system and version-specific calls, and you must never directly modify these methods. Instead, use the SysStartupCmd framework. Serious

consequences may follow if the SYS layer versions of the startup methods are not called.

When Microsoft Dynamics AX is started, calls are executed in the sequence shown in the following code.

appl.startup() // The SysStartupCmd class is instantiated here.

sysStartupCmd.applInit()

super()

sysStartupCmd.applRun()

info.startup()

sysStartupCmd.infoInit()

super()

sysStartupCmd.infoRun()

Commands Available when Microsoft Dynamics AX Starts

The commands that are available when Microsoft Dynamics AX starts are listed in the SysStartupCmd.construct method (available in the

Classes node in the Application Object Tree (AOT)). The commands include the following:

AutoRun

AOTImport

Synchronize

Execute a New Command when Microsoft Dynamics AX Starts

1. Create a class that extends the SysStartupCmd class to perform your specific task.

For example, in the standard application, the SysStartupCmdBuildNoSet class is used to set the build number. Use a similar approach

for your task.

Page 39: Query and Classes and Methods in AX 2012

2. Modify the construct method on the SysStartupCmd class so that your class is called.

Following is an example.

switch (s)

{

// Code lines are left out here.

case 'autorun':

sysStartupCmd = new SysStartupCmdAutoRun(s,parm);

break;

// Code lines are left out here.

}

3. Add parameters (if necessary) to commands that are executed on startup to the Command to run at application startup field on the

General tab in the Microsoft Dynamics AX Configuration Utility.

Instead of giving the command from the Microsoft Dynamics AX Configuration Utility, you might choose to use the command-line

parameter -startupcmd= MyCommand.

See also

Substitute Application Classes for System Classes

Batch Processing Classes [AX 2012]

Updated: February 14, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

Implement classes by using the batch processing system, and by extending the RunBase and the RunBaseBatch classes.

Remove the Recurrence button from the Batch processing dialog by using the Args::parmEnum method. For more information, see the

procedure later in this topic.

It is recommended that you designate a class to run as a server-bound batch job. Server-bound batch jobs are more secure than jobs that are not

server-bound batch for the following reasons:

The job executes by using the permissions of the user who submitted the job.

The job can interact with the Microsoft Dynamics AX client, which is processing the job, by using only certain Info and Global class

methods. This limits interaction with the client.

Enable a Class to Run as a Server-Bound Batch Job

1. Create a class that extends the RunBaseBatch class.

2. Override the RunBaseBatch.runsImpersonated method to return a value of true, as shown in the following example.

public boolean runsImpersonated()

{

return true;

}

3. Confirm that the class calls only the following Info and Global class methods:

o add

o Info.copy

o Info.cut

o Info.import

o Info.export

o Info.line

o Info.num

Page 40: Query and Classes and Methods in AX 2012

o Global::error

o Global::info

o Global::warning

The Info.line and Info.num methods are inherited from the xInfo class.

Remove the Recurrence Button from the Batch Processing Dialog

When you implement a class by using the batch processing system, call the Args.parmEnum method, and pass the NoYes::Yes system

enumeration value to remove the Recurrence button.

The NoYes system enumeration determines whether the recurrence button is removed from the batch processing dialog. The default value is

NoYes::No.

In the following code example, the InventTransferMultiShip class is implemented. The BatchDialog::main method creates the Batch processing

dialog.

static void noRecurrenceButton(Args _args)

{

Args a;

InventTransferMultiShip inventTransferMultiShip;

;

a = new Args();

inventTransferMultiShip = InventTransferMultiShip::construct();

a.caller(inventTransferMultiShip);

a.parmEnum(NoYes::Yes);

BatchDialog::main(a);

}

Page 41: Query and Classes and Methods in AX 2012

Image Manipulation Classes [AX 2012]

Updated: February 14, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

There are two system classes that enable you to manipulate graphics and icons.

The Image Class enables you to load, save, and manipulate individual images. For example, you can capture a screen and save it as an image,

crop or rotate an image, or manipulate the color depth.

The Imagelist Class enables you to work with a set of images that have some common properties, such as size and transparency color. The image

lists that are used in the application can be viewed in the application classes called ImageListAppl_*.

See also

How to: Create an Image List for Controls

Page 42: Query and Classes and Methods in AX 2012

Query Object Model [AX 2012]

Updated: February 13, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

The query object model contains classes to define and run a query. These objects are used to define the query data source, the fields returned,

record ranges and relations to child data sources. The following illustration shows the object model.

Page 43: Query and Classes and Methods in AX 2012

The query components shown in the previous figure are system classes. The query classes are more visible when you create a dynamic query in

code, but they are also used behind the scenes when you create a static query in the AOT.

System class Description

QueryRun Executes the query and fetches the data.

Query The top level of the query definition. This class holds some properties itself and has one or more related data sources.

QueryBuildDataSource Defines access to a single data source in the query. If more than one data source exists at the same level in a query, they result in separate SQL statements

that are executed sequentially. If one data source exists as a child of another data source, a join is created between the two data sources.

QueryBuildFieldList Defines which fields are returned from the database. The default is that the field list is dynamic, which returns all fields from the data source table, map,

or view. Each data source has only one QueryBuildFieldList object, which contains information on all selected fields. It's possible to specify aggregate

functions like SUM, COUNT, and AVG on the field list object.

QueryBuildRange Defines a subset of records returned based on a single field. A range is translated into a WHERE clause in the query SQL statement. If more than one field

is used to limit the query (WHERE clause), the data source will contain more than one range.

QueryBuildDynalink Contains information regarding a relation (limitation) to an external record. When the query is run, this information is converted to additional entries in

the WHERE clause of the query SQL statement. Can only exist on the parent data source of a query. The function is used by forms, when two data

sources are synchronized. Then the child data source will contain a dynalink or dynalinks to the parent data source. The function is used even if the two

data sources are placed in two different forms but are still synchronized.

QueryBuildLink Specifies the relation between the two data sources in the join. Can only exist on a child data source.

See also

How to: Create Queries by Using X++

System Classes Overview [AX 2012]

Updated: January 19, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

Page 44: Query and Classes and Methods in AX 2012

System classes (or kernel classes) are implemented in C++. The source for these classes is not available, but documentation is available for some

of the classes in the Reference content.

A system class can have:

Static methods (or class methods)

Dynamic methods

Properties: these are member functions to set properties. For example, LeftMargin.

Note

You cannot override system class methods.

It is not intended that you design your application objects from scratch by using the system classes. Instead, use them to extend or alter the

default functionality in the Application Object Tree (AOT). For example, you could dynamically add extra information to an existing report or

change the available options on a form, depending on the user's choice in a previous form.

Some of the categories of system classes are described as follows.

Collection Classes

The Collection Classes in Microsoft Dynamics AX enable you to create lists, sets, structs, maps, and arrays.

Application Objects Classes

These system classes hold functions that are activated whenever you use the AOT to create your application. For example, the system uses the

FormDesign class when you define the layout of your form in the Designs node in the Application Object Tree. When you click New CheckBox

in the AOT, the system activates the controlName method with a CheckBox type control as parameter.

These classes also enable you to create and modify application objects. For example, if you want to change a property on a form string field, see

Forms System classes and Query System Classes.

Integration Classes

The integration to the environment of Microsoft Dynamics AX is typically implemented by classes. Some examples of classes of this category

are:

COM: call of methods on COM objects

DLL: call of Microsoft Windows DLL functions

IO: Read and write external files

ODBCConnection: an ODBC interface to a foreign database

Classes Extended by Application Classes

A group of system classes whose names begin with "X" are extended by Application classes. For example, the xInfo System class is extended by

the Info Application class. For more information, see Application substituted kernel classes.

true

Page 45: Query and Classes and Methods in AX 2012

Performing Reflection with the TreeNode Class [AX 2012]

Updated: November 9, 2009

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

This topic gives information about performing reflection on Application Object Tree (AOT) items such as tables and classes. In your X++ code

in Microsoft Dynamics AX, you can use the TreeNode class to perform reflection. The TreeNode class can also add nodes to the AOT, such as

adding an element to an enumeration.

X++ Example

Description

The following code example locates the AOT node for a specific base enumeration. All child nodes are checked to determine the next available

integer value for an EnumValue. Then another child node is added under the enumeration. Finally, the code pauses so that you can inspect the

AOT for the new node. When you see the new node, you can click Yes on a dialog box. This resumes the job code, and the job deletes the new

node before it is completed.

The example relies on the following items which are installed with the system.

The #AOT macro. The macro is located in the AOT under the Macros node.

The base enumeration BankAccountType that is in the AOT under \Data  Dictionary\Base Enums\.

The example uses the following methods on the TreeNode class:

AOTadd

AOTcompile

AOTdelete

AOTfindChild

AOTfirstChild

AOTgetProperties

AOTgetProperty

AOTnextSibling

AOTsave

AOTsetProperty

AOTToString

findNode

Code

static void Job_TreeNode_AOTsave_Reflection(Args _args)

{

// #AOT is defined in the AOT under Macros.

#AOT

TreeNode tnode2Enum,

tnode3Element

;

int iMaxEnumValue = -1;

str sEnumName = "BankAccountType",

sEnumElementNameNew = "PiggyBankAccount",

sTemp;

;

// Uses the full path to obtain the node for the new enum element

// that this job creates near its completion.

tnode2Enum = TreeNode::findNode(

#BaseEnumsPath

+ "\\" + sEnumName

+ "\\" + sEnumElementNameNew

Page 46: Query and Classes and Methods in AX 2012

+ "\\" );

// Deletes the enum element node if it pre-exists.

if (tnode2Enum)

{

info("Deleting the enum element: ["

+ sEnumElementNameNew

+ "], because it pre-exists.");

tnode2Enum.AOTdelete();

}

else

{

info("Not deleting the enum element: ["

+ sEnumElementNameNew

+ "], because it does not pre-exist.");

}

// Finds the node for the target enum, by searching for the name.

tnode2Enum = TreeNode::findNode(#BaseEnumsPath);

tnode2Enum = tnode2Enum.AOTfindChild(sEnumName);

if (tnode2Enum == null)

{

Error("Cannot find treeNode: " + sEnumName);

return;

}

info( "AOToString: " + tnode2Enum.AOTToString() );

// Gets the first child node of the enum.

tnode3Element = tnode2Enum.AOTfirstChild();

info("");

info("Properties of the first child element:");

info(tnode3Element.AOTgetProperties());

info("");

// Inside the while loop the AOTnextSibling method is called.

// This enables the loop to process each child node of the enum.

// An alternative is to use a TreeNodeIterator that is obtained

// from the AOTiterator method.

while (tnode3Element)

{

if ( iMaxEnumValue < any2int(

tnode3Element.AOTgetProperty("EnumValue"))

)

{

iMaxEnumValue = tnode3Element.AOTgetProperty("EnumValue");

}

info( "iMaxEnumValue == " + int2str(iMaxEnumValue) );

tnode3Element = tnode3Element.AOTnextSibling();

}

++iMaxEnumValue;

// The call to AOTadd on the parent returns a new child node of the enum.

tnode3Element = tnode2Enum.AOTadd("PiggyBankAccount");

// Sets the numeric property on the new child.

tnode3Element.AOTsetProperty("EnumValue", iMaxEnumValue);

// Saves the new child into the system by saving the parent enum.

// Then the new child node appears in the AOT.

tnode2Enum.AOTcompile();

tnode2Enum.AOTsave();

// Asks the user to verify that the AOT displays the new node.

sTemp = "Is the new element displayed in the AOT?";

warning(sTemp);

print(sTemp);

print("Then click 'Yes' to resume and finish the job,"

+ " to delete the new element.");

Page 47: Query and Classes and Methods in AX 2012

print("Or, click 'No' to end the job,"

+ " to leave the new node in the AOT.");

pause;

// Cleans up by deleting the newly added element.

tnode2Enum = TreeNode::findNode(

#BaseEnumsPath

+ "\\" + sEnumName

+ "\\" + sEnumElementNameNew

+ "\\" );

if (tnode2Enum)

{

info("Deleting the enum element: ["

+ sEnumElementNameNew

+ "], because the add did work.");

tnode2Enum.AOTdelete();

}

else

{

error("Not deleting the enum element: ["

+ sEnumElementNameNew

+ "], because the add did not work.");

}

}

Output

The output to the Infolog is as follows: Message (11:16:07 am)

Deleting the enum element: [PiggyBankAccount], because it pre-exists.

AOToString: Path: \Data Dictionary\Base Enums\BankAccountType Layer: usr

Properties of the first child element:

PROPERTIES

Name #CheckingAccount

Label #@SYS95020

ConfigurationKey #

EnumValue #0

ENDPROPERTIES

iMaxEnumValue == 0

iMaxEnumValue == 1

Is the new element displayed in the AOT?

Deleting the enum element: [PiggyBankAccount], because the add did work.

See also

Microsoft Dynamics AX Class Overview

TreeNode Class

MemberFunction Class

MethodInfo Class

ClassBuild Class

Page 48: Query and Classes and Methods in AX 2012

Performing File IO with the TextIo Class [AX 2012]

Updated: August 14, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

X++ code performs file input and output (IO) by using the TextIo class. TextIo uses Unicode.

X++ Sample

The following X++ job code sample creates a file and writes to it. Next the code reads from the file, and prints every record to the Infolog.

The use of the FileIOPermission class is also illustrated. FileIoPermission is used to assert that the current method has the authority to call

another method that checks for such authority. For more information, see Code Access Security.

static void Job_File_IO_TextIo_Write_Read(Args _args)

{

TextIo txIoRead,

txIoWrite;

FileIOPermission fioPermission;

container containFromRead;

int xx,

iConLength;

str sTempPath,

sFileName = "Test_File_IO.txt",

sOneRecord;

;

// Get the temporary path.

sTempPath = WINAPI::getTempPath();

info("File is at: " + sTempPath + sFileName);

// Assert permission.

fioPermission = new FileIOPermission

(sTempPath + sFileName ,"RW");

fioPermission.assert();

// If the test file already exists, delete it.

if (WINAPI::fileExists(sFileName))

{

WINAPI::deleteFile(sTempPath + sFileName);

}

// Open a test file for writing.

// "W" mode overwrites existing content, or creates the file.

txIoWrite = new TextIo( sTempPath + sFileName ,"W");

// Write records to the file.

txIoWrite.write("Hello World.");

txIoWrite.write("The sky is blue.");

txIoWrite.write("");

txIoWrite.write("// EOFile");

// Close the test file.

txIoWrite = null;

// Open the same file for reading.

txIoRead = new TextIo(sTempPath + sFileName ,"R");

// Read the entire file into a container.

Page 49: Query and Classes and Methods in AX 2012

containFromRead = txIoRead.read();

// Loop through the container of file records.

while (containFromRead)

{

sOneRecord = "";

iConLength = conLen(containFromRead);

// Loop through the token in the current record.

for (xx=1; xx <= iConLength; xx++)

{

if (xx > 1) sOneRecord += " ";

sOneRecord += conPeek(containFromRead ,xx);

}

info(sOneRecord);

// Read the next record from the container.

containFromRead = txIoRead.read();

}

// Close the test file.

txIoRead = null;

// Delete the test file.

WINAPI::deleteFile(sTempPath + sFileName);

// revertAssert is not really necessary here,

// because the job (or method) is ending.

CodeAccessPermission::revertAssert();

}

X++ Sample Output

The following is the actual Infolog output.

Note

Several spaces between Hello and World are condensed to one space in the output. This occurs because the read method uses a string of one or more space characters as a delimiter of

tokens, and only the tokens are put into the returned container.

Message (14:12:47)

File is at: C:\DOCUME~1\myalias\LOCALS~1\Temp\Test_File_IO.txt

Hello World.

The sky is blue.

// EOFile

See also

Microsoft Dynamics AX Class Overview

TextIo Class

CommaTextIo Class

BinaryIo Class

FileIOPermission Class

TextBuffer Class

Page 50: Query and Classes and Methods in AX 2012

Queries in the AOT for Data Access [AX 2012]

Updated: February 8, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

Queries enable you to ask questions about the data in the Microsoft Dynamics AX database and retrieve information. There are two ways to

create queries:

Use the Queries node in the Application Object Tree (AOT) to create static queries using a graphical interface. For more information

about creating queries in the AOT, see How to: Create Queries by using the AOT.

Use the query system classes to create dynamic queries in code. For more information about creating queries in code, see How to:

Create Queries by Using X++.

See also

Query Elements in the AOT

How to: Create Queries by using the AOT

How to: Create Queries by Using X++

Page 51: Query and Classes and Methods in AX 2012

Accessing Data [AX 2012]

Updated: March 7, 2011

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

Queries enable you to ask questions about the data in the Microsoft Dynamics AX database and retrieve information. There are two ways to

create queries:

Use the Queries node in the Application Object Tree (AOT) to create static queries using a graphical interface. For more information,

see How to: Create Queries by using the AOT.

Use the query system classes to create dynamic queries in code. For more information, see How to: Create Queries by Using X++.

No matter which method that you use to create a query, the query can include a sorting order to sort the information that is returned. It can also

include a range to filter the information that is returned based on your criteria.

A query can return data from multiple data sources. For more information, see How to: Add Multiple Data Sources to a Query.

You can create queries for forms and reports. For more information, see How to: Coordinate Two Forms by Overriding an Event Method.

Paging

When you create a query with X++, you can add paging support to that query. Paging retrieves the results of a query as a collection of one or

more data subsets known as pages. The QueryRun class supports the following types of paging:

Position based paging divides the query result into pages and enables you to display the data records represented by a specified page.

Value based paging uses a page to represent the data records that are currently displayed in a data grid. Use value based paging when

you want an update to a data grid to automatically redisplay the same set of data records.

To enable paging, use the enablePositionPaging and enableValueBasedPaging methods of the QueryRun class. To use paging with a query, the

query cannot have a disabled data source. Also, the value of the FirstOnly property of the data source must be set to No.

See also

Customizing the Query Form

Query Properties

Query System Classes

Using Expressions in Query Ranges

Page 52: Query and Classes and Methods in AX 2012

Walkthrough: Creating an AOT Query that has Group By and Having Nodes [AX 2012]Updated: August 31, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

In this walkthrough you create Group By and Having nodes under a query in the Application Object Tree (AOT).

The query you create shows the number of customer records for each destination code where there are more than six customers and the

destination code is not equal to Gen_5. If the query you create was represented in standard ANSI SQL, the select query would look like the

following: select

ct.DestinationCodeId

,count(*)

from

CustTable as ct

where

ct.DestinationCodeId != 'Gen_5'

group by

ct.DestinationCodeId

having

count(*) > 6

order by

1;

Note

In the example of this topic the query has its AllowCrossCompany property set to Yes. This setting means the query does no filtering on company or party.

Create the Query Entry

You create the query in the AOT by the following steps:

1. Expand AOT > Queries.

2. Right-click the Queries node, and then click New Query.

3. In the Properties window, edit the Name property value to be QryGbyHavgRange23.

4. Set the AllowCrossCompany property to Yes.

5. Right-click your QryGbyHavgRange23 node, and then click Save to confirm the node and property changes.

Page 53: Query and Classes and Methods in AX 2012

6. Expand the node for your new query, so that you can see its subnodes including its Data Sources subnode.

7. Proceed to create the subnodes that are described in the table that follows.

Add a Data Source

Next you must add a data source node to your query.

Subnode Steps Properties window

Data

Sources

Add the CustTable as a data source.

1. Right-click Data Sources, and then click New Data Source.

This creates a new node under Data Sources.

2. Click the new data source node to highlight it.

3. In the Properties window, set the Table property to CustTable. This

action also changes the value of the Name property.

This query reads data from only one table, the CustTable table.

Add Subnodes Under Data Sources

The following table shows the steps to create each subnode under

 AOT > Queries > QryGbyHavgRange23 > Data Sources. The table also shows the Properties window for each subnode.

Subnode Steps Properties window

Fields Add a field under the new CustTable data source node.

1. Expand the new data source node.

2. Right-click the Fields node, and then click New > COUNT.

3. In the Properties window for the new field node, set the Field property to RecId.

ANSI SQL typically uses an asterisk for the count aggregate function. But in Microsoft Dynamics

AX a field must be used, and by convention the RecId field is usually used.

Ranges Add a range node to exclude one particular value of the DestinationCodeId field. Each range node

applies to the Where clause of the SQL Select statement that is eventually generated.

1. Right-click the Ranges node, and then click New Range.

2. Set the Field property to DestinationCodeId.

3. Set the Value property to != "Gen_5".

Notice that the Value property is set to both a comparison operator and a specific data value.

Inclusion of an operator is optional.

Page 54: Query and Classes and Methods in AX 2012

Group

By

Add a Group By clause. A query cannot have a Having clause unless it also has a Group By clause.

For each unique value in the DestinationCodeId field, the query counts all the CustTable records

that share the same DestinationCodeId value with each other. This is accomplished by adding a

group by clause.

1. Right-click the Group By node, and then click New Field.

2. In the Properties window, set the Field property to DestinationCodeId.

Implicitly the system adds the group by field to the fields list at run time, so that the group by field is

also returned when the query is run.

Having Add a Having clause to filter the aggregate values that are generated by the Group By clause. In the

present example, the COUNT(RecId) field contains the aggregate values that are filtered.

1. Right-click the Having node, and then click New > COUNT.

2. In the Properties window, set the Field property to RecId.

3. Set the Value property to > 6.

The value filter is compared against the COUNT aggregate result of each record that otherwise can

be returned. The value is not compared against the RecId field.

Order

By

Add an Order By node. The order by clause operates on the records that remain after all the filtering

is completed.

1. Right-click the Order By node, and then click New Field.

2. In the Properties window, set the Field property to DestinationCodeId.

3. Set the Direction property to Descending.

4. Right-click the QryGbyHavgRange23 node, and then click Save.

Next is an image of how the finished query looks when it is fully expanded in the AOT:

 

Note

Page 55: Query and Classes and Methods in AX 2012

The preceding screen images were taken from an installation of Microsoft Dynamics AX 2012.

X++ Code to Run the Query

You can use the following X++ code to run the AOT query created in the previous procedure. The code is an X++ job that you can paste into a

new job under AOT > Jobs.

static void QryGbyHavgRange23Job(Args _args) // X++ job.

{

CustTable ct;

Query q = new Query(queryStr(QryGbyHavgRange23));

QueryRun qr = new QueryRun(q);

while(qr.next())

{

ct = qr.get(tableNum(CustTable), 1);

info(strFmt("(Q23) , %1 , %2",

ct.DestinationCodeId, ct.RecId));

}

info("Done.");

}

/*** Infolog display of results:

Message (04:11:40 pm)

(Q23) , Gen_9 , 8

(Q23) , Gen_8 , 11

(Q23) , Gen_7 , 10

(Q23) , Gen_4 , 15

(Q23) , Gen_3 , 8

(Q23) , Gen_2 , 21

(Q23) , , 26

Done.

***/

See also

Queries in the AOT for Data Access

Page 56: Query and Classes and Methods in AX 2012

Cross-Company Data Access [AX 2012]

Updated: February 14, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

A cross-company query returns data for several companies in a single run. A query does not have to be limited to returning data for the current

session company. A cross-company query operates over all companies that you have read permissions for, or over a subset of companies that

you specify.

How to Create a Cross-Company Query

To create a cross-company query:

In X++, use the crossCompany keyword on the X++ select statement.

In X++, set the allowCrossCompany property method to true on an instance of the Query class.

In the AOT, set the AllowCrossCompany property to Yes on a node under Query.

Cross-Company Querying in Forms

You can also design cross-company query behavior into dynamically linked parent and child form pairs. One important step in creating such

forms is to set the FormDataSource.crossCompanyAutoQuery to true. Or in the AOT, set the CrossCompanyAutoQuery property to Yes on a

node under the Data Sources of a Form.

Equivalent to Unions

The results returned for an X++ select crossCompany query match what could be returned by a union of several select statements that each

omits the crossCompany keyword.

In the Microsoft Dynamics AX client, you could set your current session company to CM1, then run a select query and save the results. You

could switch to company CM2, rerun the query, and then add the results to the earlier results. You could repeat this cycle for all the companies

you are authorized to see. Your accumulated results would be the same as running one select crossCompany.

In This Section

Cross-Company X++ Code Basics

Cross-Company and the company Getter Method

Cross-Company Queries for Views

Cross-Company Reports in the AOT

See also

Page 57: Query and Classes and Methods in AX 2012

Queries in the AOT for Data Access

Cross-Company X++ Code Basics [AX 2012]

Updated: February 20, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

You can create a cross-company query by using X++ code. There are two ways to do this:

crossCompany keyword on the select statement

Query class methods

A cross-company query can also be created under the Query node in the Application Object Tree (AOT).

A cross-company query cannot return data for companies that the user does not have permission to access. A cross-company query can be

limited to a subset of the companies that the user is authorized to access.

The cross-company query is useful if at least one of the tables has the SaveDataPerCompany property set to Yes.

crossCompany Keyword

You can create a cross-company query by using the crossCompany keyword on the X++ select statement. You have the option of adding a

container variable of company identifiers immediately after the crossCompany keyword (separated by a colon). The container restricts the

selected rows to those with a dataAreaId that match a value in the container.

The following code example populates a table buffer with all the BankAccountTable rows that have a dataAreaId of either cm1 or cm2 or dat.

This example assumes that the user has authority to access data for these three companies. The first two dataAreaId values that are found will be

printed.

static void JobDemoCrossCompany(Args _args)

{

BankAccountTable tabBAT; // saveDataPerCompany == true.

container conCompanies = [ 'cm1', 'cm2', 'dat' ];

str 4 sCompanyPrevious = " "; // Maximum length is 4 characters.

int iCountCompanies = 0;

;

while select

Page 58: Query and Classes and Methods in AX 2012

crossCompany

: conCompanies

* from tabBAT

order by dataAreaId

{

if ( sCompanyPrevious != tabBAT.dataAreaId )

{

info( tabBAT.dataAreaId + " = tabBAT.dataAreaId" );

iCountCompanies++;

if ( iCountCompanies >= 2 )

{

break;

}

sCompanyPrevious = tabBAT.dataAreaId;

}

}

return;

}

Query Class

In X++ code you can use the Query .allowCrossCompany property method to achieve the same result as you can with the crossCompany

keyword on a select statement. The calls to the Query .addCompanyRange method are the same as appending a container of companies to the

crossCompany keyword.

You cannot perform data source level filtering by company in a cross-company query. This is why the call to qbds3 .company is commented out

in the following code example.

static void JobDemoAllowCrossCompany(Args _args)

{

BankAccountTable tabBAT; // saveDataPerCompany == true.

Query qry2;

QueryBuildDataSource qbds3;

QueryRun qrun4;

str sCompanyPrevious = " ";

int iCountCompanies = 0;

int iTableNumBAT;

;

qry2 = new Query();

qry2.allowCrossCompany( true );

qry2.addCompanyRange( 'dat' );

qry2.addCompanyRange( 'twf' );

iTableNumBAT = tableNum( BankAccountTable );

qbds3 = qry2 .addDataSource( iTableNumBAT );

//qbds3.company( 'dat' );

qrun4 = new QueryRun( qry2 );

while ( qrun4.next() )

{

if ( qrun4.changed( iTableNumBAT ) )

{

tabBAT = qrun4.get( iTableNumBAT );

if ( sCompanyPrevious != tabBAT.dataAreaId )

{

print( tabBAT.dataAreaId + " = tabBAT.dataAreaId" );

iCountCompanies++;

if ( iCountCompanies >= 2 )

{

break;

}

sCompanyPrevious = tabBAT.dataAreaId;

}

}

}

pause;

Page 59: Query and Classes and Methods in AX 2012

return;

}

Query in the AOT

In the AOT, you can get cross-company functionality from a query node by setting the AllowCrossCompany property to Yes (the equivalent of

true in X++ code). You can override methods on the node of your query to call the Query.addCompanyRange method.

For more information, see Cross-Company Reports in the AOT.

See also

Cross-Company Data Access

DataArea Table

Cross-Company Data Modification Using X++ [AX 2012]

Updated: February 13, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

You can use a while select crossCompany statement for cross-company data modification. You may need to use this statement because you

cannot use the crossCompany keyword in X++ SQL statements that modify data nor can you use sub-select commands embedded in data

modification statements. You can issue a while select crossCompany statement first, and then use the populated table buffer to drive data

modification commands. The changeCompany keyword is a central part of this technique.

Data Modification Options

In X++, you can modify data with either SQL statements or with methods on a table buffer. The SQL statements are best for modifying a set of

rows with one command. The methods are used to modify one row per call.

The SQL data modification statements are:

delete_from

insert_recordset

update_recordset

The data modification methods on a table buffer variable are inherited from the xRecord class. These methods are:

delete

Page 60: Query and Classes and Methods in AX 2012

insert

update

All of these options can be used in cross-company data modification processing.

delete_from Command

In X++ code, you can delete data on a cross-company basis, even though you cannot use the crossCompany keyword on the delete_from

statement. The following code example shows one way you can do this.

static void JobCCDel( Args _args )

{

Table21 tab21a , tab21b;

;

ttsBegin;

while select

crossCompany

minof( ratingNum )

, dataAreaId

from

tab21a

group by

dataAreaId

{

changeCompany( tab21a .dataAreaId )

{

tab21b = null;

delete_from tab21b

where tab21b .ratingNum == tab21a .ratingNum;

}

}

ttsCommit;

}

insert Method

The following X++ code example shows how to use the cross-company feature for inserting data, even though the crossCompany keyword

cannot be used on the insert_recordset command.

static void JobCCIns( Args _args )

{

Table21 tab21;

Table22 tab22;

;

ttsBegin;

while select

crossCompany

actionDate , name , dataAreaId

from

tab21

where

tab21 .actionDate > str2Date( '1998-01-22' , 321 )

{

changeCompany( tab21 .dataAreaId )

{

tab22 = null;

tab22 .actionDate = tab21 .actionDate;

tab22 .name = tab21 .name;

tab22 .insert();

}

}

ttsCommit;

}

update_recordset with forUpdate on select

Page 61: Query and Classes and Methods in AX 2012

This X++ example uses the forUpdate keyword on the while select crossCompany statement. Only one table buffer variable is declared. This

example also uses the update method on the table buffer.

static void JobCCForUpdMethod( Args _args )

{

Table21 tab21;

;

ttsBegin;

while select

forUpdate crossCompany

countOfReviews

from

tab21

{

changeCompany( tab21 .dataAreaId )

{

tab21 .countOfReviews = tab21 .countOfReviews + 2;

tab21 .update();

}

}

ttsCommit;

}

Cross-Company Methods and Properties [AX 2012]

Updated: February 9, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

In X++ code, you can call functions that are related to cross-company functionality by using:

Query class methods

changeCompany X++ keyword

In X++ code, you can set properties that are related to cross-company functionality by using:

allowCrossCompany on a Query instance

company on a table buffer (extended from xRecord class)

crossCompanyAutoQuery on a FormDataSource instance

Just as these properties can be set in X++ code, they can also be set in the Application Object Tree (AOT). These methods can be called in

methods overridden in the AOT.

Functions

Page 62: Query and Classes and Methods in AX 2012

Methods on the Query class

In X++ code, after you create an instance of the Query class, you can call several instance methods that are related to cross-company

functionality. These query methods are relevant only if you set the query's allowCrossCompany property to true:

addCompanyRange

clearCompanyRange

getCompanyRange

If you do not call addCompanyRange, the query returns data for all companies that the user has authority to read. You can call

addCompanyRange to restrict the range of company data that the query returns. The first call to addCompanyRange minimizes the data that the

query returns because data is returned for only the first company that is added. Subsequent calls to addCompanyRange increase the amount of

data returned by the query.

The clearCompanyRange method cancels the earlier calls to addCompanyRange. The clearCompanyRange method has no effect if

addCompanyRange has not been called.

The getCompanyRange method returns a container of dataAreaId values that have been added.

changeCompany Keyword

The X++ language has a keyword changeCompany. You use changeCompany to create a bracketed scope in which the active company can

differ from your session company.

The keyword changeCompany is used in data modification processing in cross-company scenarios.

For more information about how to use changeCompany for data modification in cross-company scenarios, see Cross-Company Data

Modification Using X++.

For more information about how to use the changeCompany keyword beyond cross-company processes, see Change Company Design Pattern.

Properties

There are properties you can set that are related to cross-company functionality. In X++ these can be either properties or property methods

(which are small methods that get and set a state of the object). In the AOT, these appear in the Properties window.

AllowCrossCompany Property on Query

In the AOT, each query node has the AllowCrossCompany property. The default value is No. You can set this property to Yes to make the

query return data for all companies that you are authorized to read from.

This is the same property that can be accessed in X++ code on an instance of the Query class.

Company Property on xRecord Buffers

In X++ code, a buffer variable can be declared for a table. For the BankAccountTable, the buffer declaration could be: BankAccountTable

myBat;. The myBat variable inherits all the methods and properties from the xRecord class.

One of the properties inherited by a table buffer is company. In X++, the syntax is a pair of get and set property methods (the setter takes a

parameter).

In the AOT, this property is not present on tables that are immediately under the Tables node. But when a table is dragged onto a query's Data

Sources node, that new table node has the Company property. The default setting is blank.

This Company property must be left blank when the AllowCrossCompany property is set to Yes.

Purpose of Setting the Company Property

When AllowCrossCompany is No, you can set a data source's Company property to a non-blank value to alter the current company context, as

an override to the current session company. This is similar to using the changeCompany keyword in X++ code, although the scope or duration

of the change is different.

You can set Company to a value to automate agreements between two companies. For example, the creation of a purchase order might

automatically generate an invoice for the other company.

See also

Cross-Company X++ Code Basics

Page 63: Query and Classes and Methods in AX 2012

Cross-Company and the company Getter Method [AX 2012]

Updated: June 7, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

The dataAreaId value returned by the company getter method on table buffer variables can differ between cross-company versus single-company

scenarios.

For information about how a table buffer variable inherits company from the xRecord class, see Cross-Company Methods and Properties.

Page 64: Query and Classes and Methods in AX 2012

Tables can be categorized into the following types:

Global - The SaveDataPerCompany property is set to No.

Company-specific - The SaveDataPerCompany property is set to Yes.

Shared - Company-specific tables associated with a virtual company.

These different types of tables interact differently with the cross-company feature. In cross-company scenarios, the current company can be

different from the company of the row currently being processed by the application X++ code. This difference has implications for the company

getter method.

Note

The current company (the user's session company) is shown in the status bar in the lower-right portion of the Microsoft Dynamics AX client window.

Global Tables and the company Method

For a table buffer variable declared from a global table, the company getter method returns the user's session company. Global tables do not have

the field named dataAreaId.

Company-Specific Tables and the company Method

A table buffer variable declared from a company-specific table can be populated by a while select crossCompany statement. This populates the

buffer with rows that represent a variety of companies. When a buffer is populated in this manner, the company method returns the dataAreaId

value of the buffer's current row, regardless of the user's session company.

Shared Tables and the company Method

For some rows in a shared table, the dataAreaId field can have a value representing the virtual company that the table is associated with. Other

rows can have dataAreaId values for real companies that are outside of the virtual company.

The following X++ code example populates the table buffer with a row set from a shared table that has both kinds of dataAreaId values.

while select crossCompany * from SH_buffer { /* X++ */ }

The following descriptions assume that the shared table is associated with virtual company VC9. The descriptions assume that VC9 is associated

with real companies CM1 and CM2.

During the while select loop that processes rows of each dataAreaId value, the company getter method on the table buffer returns values

according to the following table.

Test case number dataAreaId in shared table's current row Current session company Returned by company getter method

1 VC9 CM1 CM1

2 VC9 CM2 CM2

3 VC9 CM3 Either CM1 or CM2, whichever the user has greater permissions on.

For example, Delete permission is greater than Read permission.

4 CM3 (Any company) CM3

Note

In Microsoft Dynamics AX 2009 the above table describes the behavior when either a table or a view is the subject of the while select. In the previous version, it applied to tables but

not to views.

Page 65: Query and Classes and Methods in AX 2012

Rules Governing the company Method

The following rules govern the behavior of the company getter method of table buffer objects:

The session company can never be a virtual company.

The company method never returns a value that conflicts with the dataAreaId of the current row. The dataAreaId takes precedence

over the session company.

The company method never returns the dataAreaId value of a virtual company. Instead, a real company in the virtual company is

returned.

When the current row has the dataAreaId of a virtual company, the company method returns one of the real companies in the virtual

company.

After the clear method is called on a table buffer, the company getter method retrieves the current company of the client. However, this

is not true for temporary tables.

Greater Permissions Factor for Test Case 3

Test case number 3 in the preceding table shows that sometimes the system chooses which real company to return when the company method is

called. In cases where the session company is not part of the current row's virtual company, the company method returns whichever real

company the user has the most permissions for.

In test case 3, if the user has both read and insert permission for CM1, but only read permission for CM2, then CM1 is returned.

The system determines which real company the user has greater permissions for only when the session company is not in the virtual company.

See also

Best Practices for Table Collections

Table Properties

xRecord.company Method

Cross-Company Queries for Views [AX 2012]

Updated: February 20, 2012

true

Page 66: Query and Classes and Methods in AX 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

In the Application Object Tree (AOT), you can build a view by dragging a query node onto the Data Sources node of your view. The query

could have the AllowCrossCompany property set to Yes. However, this will not return cross-company results from the view.

To return cross-company results from a view, you need to use the crossCompany keyword on the select statement that reads from the view. The

AllowCrossCompany setting on the view's data source query is ignored in X++ select statements that read from a view.

See also

Cross-Company X++ Code Basics

Cross-Company Reports in the AOT [AX 2012]

Page 67: Query and Classes and Methods in AX 2012

Updated: February 20, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

You can use the Application Object Tree (AOT) to create a cross-company report. The simplest way to create a report is to set the

AllowCrossCompany property to Yes on your query. Then drag the query node onto your report's Data Sources node.

To fully control the cross-company behavior of an AOT query or report, you must understand the relationships between:

AOT query node

Query class

QueryRun class

For basic information about cross-company queries, see Cross-Company X++ Code Basics.

Relationships between AOT, Query, and QueryRun

The properties of an AOT query node match the Query class. The methods available for override on a query node match the QueryRun class.

The QueryRun class has a property method named query, which is the query instance it will run. You can access this QueryRun .query property

in methods that you override on the Queries node of the AOT. This enables you to control the details of the cross-company behavior at run time.

AllowCrossCompany Property

In the AOT, query node objects have the AllowCrossCompany property listed in the Properties window. For new queries the default value is

No (which is equivalent to false in X++ code). To make a query cross-company you need to set AllowCrossCompany to Yes.

The classes QueryRun and Query both have the AllowCrossCompany property, but their values always equal each other. When you read

AllowCrossCompany from QueryRun, QueryRun reads it from Query. When you set AllowCrossCompany on QueryRun, it sets in on Query.

Note

Although the QueryRun class and Query classes both have the allowCrossCompany property, only the Query class has the cross-company methods such as addCompanyRange.

Company Range Methods in AOT Reports

You can override methods on the AOT report node to control the details of cross-company behavior. For example, you could override the

report's init method with the following X++ code.

public void init()

{

super();

this.query().allowCrossCompany( true );

this.query().addCompanyRange( "dat" );

this.query().addCompanyRange( "dmo" );

}

See also

MorphX Reporting Tools

Page 68: Query and Classes and Methods in AX 2012

How to: Add Multiple Data Sources to a Query [AX 2012]

Updated: December 13, 2011

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

You can add parent and child data sources to a query.

Note

If you add data sources at the same level, separate SQL statements are executed sequentially.

To manage changes to AOT objects, a version control system is available. For more information, see Version Control System.

Add multiple data sources to a query

1. In the Application Object Tree (AOT), click Queries, locate the query you want to add data sources to, and then click the query node.

For information about create queries, see Accessing Data.

2. Right-click Data Dictionary, and then click Open New Window.

3. Drag a table, map, or view from the new window to the Data Sources node below the query node to add a parent data source.

4. Click the parent data source, and then drag a table, map, or view from the new window to the Data Sources node below the parent

data source to add a child data source.

5. Specify how the parent and child data sources are joined by setting the JoinMode property on the child data source

6. Create a relationship between the data sources. This information is provided later in the topic.

The following table describes the available values for the JoinMode property.

Value Description

InnerJoin Combines records from two data sources whenever there are matching values in a common field.

For example, if you selected the records that show orders placed by each customer, the query would select only records for customers who placed orders.

OuterJoin Joins all the records in one data source even if there are no matching values in the joined field from the second data source.

This allows you to return records that do not have a corresponding match in the joined table. For example, data is required from all employees and their respective

departments from the Employee table. As long as all employees are assigned to a department, an InnerJoin works. However, the president of the company does not

have a department, and an inner join between the tables will not retrieve this data. The solution to this kind of problem is an outer join.

ExistsJoin Combines records from one data source whenever there a value exists in a common field in another data source.

ExistsJoins are like InnerJoin, but MorphX uses only the embedded data source as a condition. Thus, the records in the embedded data source are not fetched by the

query. The query will fetch the records in the primary data source only if a match is made with the embedded data source.

NoExistsJoin Selects records from one data source whenever a value in a common field in another data source does not exist. The opposite of ExistsJoin.

Create a Relationship Between the Data Sources

Set the Relations property to Yes on the child data source.

-or-

Page 69: Query and Classes and Methods in AX 2012

Add a relation by doing the following:

1. Set the Relations property to No on the child data source.

2. Right-click the Relations node, and then click New Relation.

3. Select a field from the parent data source in the Field property.

4. Select a field from the child data source in the RelatedField property.

5. Save all modifications.

See also

Customizing the Query Form

Query Properties

Using Expressions in Query Ranges

Page 70: Query and Classes and Methods in AX 2012

Customizing the Query Form [AX 2012]

Updated: February 3, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

The Query form is displayed prior to a query being run and enables users to change the elements of a query. Use the Query form to do the

following:

Modify data sources.

Specify ranges.

Define a sort order.

Save the query.

By default, the Query form is the SysQueryRun form that's specified by a query's Form property. To implement your own Query form, create a

form, and then set the Query.Form property to the name of the custom form.

Display the Query Form from the Application Object Tree

1. Navigate to the Queries node.

2. Right-click the query, and then select Open.

The Query form uses the SysQueryRun application class, which extends the QueryRun kernel class.

Display the Query Form from Code

Display the Query form from code by using the QueryRun.prompt method. The following example instantiates the SalesQuotationUpdate query,

displays the Query form by calling the prompt method, and then iterates through the returned records.

static void RunSalesQuotationUpdate(Args _args)

{

QueryRun SalesQuotationUpdate;

SalesQuotationTable SalesQuotationTable;

;

SalesQuotationUpdate = new QueryRun(QueryStr(SalesQuotationUpdate));

if (SalesQuotationUpdate.prompt())

{

while (SalesQuotationUpdate.next())

{

if (SalesQuotationUpdate.changed(tablenum(SalesQuotationTable)))

{

SalesQuotationTable = SalesQuotationUpdate.get(

tablenum(SalesQuotationTable));

Page 71: Query and Classes and Methods in AX 2012

info(SalesQuotationTable.QuotationId);

}

}

}

}

Customize the Query Form

Customize the Query form by calling methods that are available from the SysQueryRun class. The following table describes the options that can

be set for the Query form.

Option When the value is set to Default

Allows the user to add a child data source. SysQueryRun.promptAllowAddDataSource

    (true);

true

Allows the user to add a range. SysQueryRun.promptAllowAddRange

    (QueryAllowAdd::AllFields);

QueryAllowAdd::

AllFields

Allows the user to add a sort order. SysQueryRun.promptAllowAddSorting

    (QueryAllowAdd::AllFields);

QueryAllowAdd::

AllFields

Allows the user to save or delete the query. SysQueryRun.promptAllowSave(true); true

Displays and loads the Query form with the query that was last run, its data sources, ranges, and sort orders. SysQueryRun.promptLoadLastUsedQuery

    (true);

true

Allows queries to be saved for each user. Users can also delete their own saved queries. SysQueryRun.promptSaveQueryPrUser

    (true);

true

Allows users to change and save their queries. If false, the user cannot change or save a query. Query.userUpdate(true); true

Displays the Query form's Select query combo box. SysQueryRun.promptShowQuerySelect

    (true);

true

Displays the Reset button, which sets all the data sources, ranges, and sort orders to their original states. SysQueryRun.ShowReset(true); true

Displays the Sorting tab. SysQueryRun.promptShowSorting

    (true);

true

Page 72: Query and Classes and Methods in AX 2012

See also

Query Elements in the AOT

Accessing Data

How to: Create Queries by Using X++

How to: Create Queries by using the AOT

Query Object Model

Query Record Retrieval Sequence [AX 2012]

Updated: February 3, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

When a query is designed in the Application Object Tree (AOT), it can access data from multiple data sources. These data sources can be created

at the same level as each other or nested in a parent-child relationship. The sequence of the retrieved records depends on how the data sources

are linked.

Outer Joins

If a single data source is nested as shown in the following figure and the JoinMode property is set to OuterJoin, the records are fetched in the

following sequence:

A1, B1, A2, B2, A3, B3,…An, Bn

A data source with a single child data source

If more than one data source is nested, the child data sources are at the same level as shown in the following figure. The JoinMode property is set

to OuterJoin, and the records are fetched in the following sequence:

A1, B1...Bn, C1…Cn, A2,…An, B1…Bn, C1…Cn

Page 73: Query and Classes and Methods in AX 2012

A data source with multiple child data sources

Inner Joins

If nested data sources have an inner join, records are fetched in the following sequence:

A1, B1, C1, A2, B2,…An, Bn, Cn

Exists Joins

If nested data sources have an exists join, records are only fetched from the primary data source as follows:

A1, A2, A3, A4…An

See also

How to: Add Multiple Data Sources to a Query

Query Properties

How to: Create Queries by Using X++ [AX 2012]

Updated: July 13, 2012

Applies To: Microsoft Dynamics AX 2012 R3, Microsoft Dynamics AX 2012 R2, Microsoft Dynamics AX 2012 Feature Pack, Microsoft

Dynamics AX 2012

In Microsoft Dynamics AX, you can create a query to retrieve data by using the query classes. For more information, see Query Object Model.

In addition, by using X++ code, you can create a query and then save that query to the Application Object Tree (AOT).

You can also create a query by using the AOT. For more information, see How to: Create Queries by using the AOT.

Create a Query by Using X++

1. Add a class to the AOT. For more information about adding a class, see Declaration of Classes.

2. Add a class method that creates a query by using the Query system classes.

In the following example, the QueryRun class runs the query specified by the q object. The addDataSource method specifies

CustTable as the data source for the query. The addRange and value methods specify account numbers between 4000 and 4022. The

addSortField method specifies that data is sorted on the DlvMode field.

public void runMyDynamicQuery2()

{

Query q;

QueryRun qr;

Page 74: Query and Classes and Methods in AX 2012

QueryBuildDataSource qbd;

QueryBuildRange qbr;

q = new Query();

qbd = q.addDataSource(TableNum(CustTable));

qbr = qbd.addRange(FieldNum(CustTable, AccountNum));

qbr.value(">=4000"); // Default operator is ==.

qbr = qbd.addRange(FieldNum(CustTable, AccountNum));

qbr.value("<=4022");

qbd.addSortField(FieldNum(CustTable, DlvMode));

qr = new QueryRun(q);

qr.prompt();

pause;

}

Access the Query by Using a Menu Item

1. Add a main method to the class, and call the method that you created in step 2.

2. Create an action menu item to reference the class by clicking Menu Items, right-clicking Action, and then clicking New Menu Item

in the AOT.

3. Right-click the menu item, click Properties, and set ObjectType to Class. Then select the class that you created in step 1 from the

Object property list.

You can include the menu item in forms and reports by configuring form and report controls to reference the menu item. For more

information, see Form Control Properties.

4. Add your menu item to a menu.

For example, expand AOT > Menus > SystemAdministration > Common, and then right-click New > Menu item. Fill in the

properties of the new menu item node.

Create a Query in the AOT by Using X++

The following procedure is a job that you can run in the AOT to create a query called MyQuery1, provided MyQuery1 does not already exist in

the Queries node.

1. In the AOT, right-click Jobs, and then click New Job. The Code editor window opens.

2. In the Code editor window, copy the following code, and then paste it in the Code editor.

static void CreateQuery6Job(Args _args)

{

TreeNode treeNodeObj;

Query queryObj; // Extends TreeNode class.

QueryBuildDataSource qbds;

QueryBuildRange qbr;

QueryRun qr;

CustTable xrecCustTable;

str queryName = "MyQuery1";

// Macro.

#AOT

// Delete the query from the AOT, if the query exists.

treeNodeObj = TreeNode::findNode(#QueriesPath);

treeNodeObj = treeNodeObj.AOTfindChild(queryName);

if (treeNodeObj) { treeNodeObj.AOTdelete(); }

// Add the query to the AOT.

treeNodeObj = TreeNode::findNode(#QueriesPath);

treeNodeObj.AOTadd(queryName);

queryObj = treeNodeObj.AOTfindChild(queryName);

Page 75: Query and Classes and Methods in AX 2012

// Further define the query.

qbds = queryObj.addDataSource(tablenum(CustTable));

qbr = qbds.addRange(fieldnum(CustTable, DlvMode));

qbr.value(">10");

// Compile the query.

queryObj.AOTcompile(1);

queryObj.AOTsave();

// Run the query.

qr = new QueryRun("MyQuery1");

while ( qr.next() )

{

xrecCustTable = qr.GetNo(1); // 1 means first data source.

Global::info(strFmt("%1 , %2",

xrecCustTable.AccountNum, xrecCustTable.DlvMode));

}

// Delete the query from the AOT.

treeNodeObj = TreeNode::findNode(#QueriesPath);

treeNodeObj = treeNodeObj.AOTfindChild(queryName);

treeNodeObj.AOTdelete();

}

3. Press F7 to compile, and then press F5 to run the job. A query named MyQuery1 is created in the Queries node. The query is run, and

then is deleted.

SysQueryRangeUtil Class has Incompatibilities with .NET CIL

In your X++ code, you can use certain methods of the SysQueryRangeUtil class to build query range values that are resolved during run time.

One such method is SysQueryRangeUtil::currentWorker(), which is shown in the following code snippet.

 QueryBuildRange myQueryBuildRange; 

 //... (More X++ code here) ... 

 myQueryBuildRange.value(queryValue(SysQueryRangeUtil::currentWorker())); 

However, if your X++ code is compiled to .NET Framework CIL, and is then run as CIL, your code might cause an error.

See also

Accessing Data

Customizing the Query Form

Using Expressions in Query Ranges

How to: Link Two Forms by Using Dynamic Links