Wednesday, November 10, 2021

Line break code in X++

str desc = 'Description :' + "\r\n" + 'This will be in Next line'

Overloading and overriding

Polymorphism means “Many Forms”. In Polymorphism, poly means “Many” and morph means “Forms.” Polymorphism is one of the main pillars in Object-Oriented Programming. It allows you to create multiple methods with the same name but different signatures in the same class. The same name methods can also be in derived classes.
 
There are two types of Polymorphism :
1. Method Overloading
2. Method Overriding


Method Overloading
Method Overloading is a type of polymorphism. It has several names like “Compile Time Polymorphism” or “Static Polymorphism” and sometimes it is called “Early Binding”. 
Method Overloading means creating multiple methods in a class with the same names but different signatures (Parameters). It permits a class, struct, or interface to declare multiple methods with the same name with unique signatures.
The compiler automatically calls the required method to check the number of parameters and their type which are passed into that method.

Sample Code

   public class Program  
    {  
        public int Add(int num1, int num2)  
        {  
            return (num1 + num2);  
        }  
        public int Add(int num1, int num2, int num3)  
        {  
            return (num1 + num2 + num3);  
        }  
        public float Add(float num1, float num2)  
        {  
            return (num1 + num2);  
        }  
        public string Add(string value1, string value2)  
        {  
            return (value1 + " " + value2);  
        }  
        static void Main(Args _args)  
        {  
            Program objProgram = new Program();  
           Info("Add with two int parameter :" + objProgram.Add(3, 2));  
           Info("Add with three int parameter :" + objProgram.Add(3, 2, 8));  
           Info("Add with two float parameter :" + objProgram.Add(3 f, 22 f));  
           Info("Add with two string parameter :" + objProgram.Add("hello", "world"));  
           
        }  
    }  


In the above example, you can see that there are four methods with the same name but the type of parameters or number of parameters is different. When you call Add(4,5), complier automatically calls the method which has two integer parameters and when you call Add(“hello”,” world”), complier calls the method which has two string parameters. So basically in method overloading complier checks which method should be called at the time of compilation.
Note: Changing the return type of method does not make the method overloaded. You cannot create method overloaded vary only by return type.



Method Overriding
Method Overriding is a type of polymorphism. It has several names like “Run-Time Polymorphism” or “Dynamic Polymorphism” and sometimes it is called “Late Binding”. 
Method Overriding means having two methods with the same name and same signatures [parameters], one should be in the base class and another method should be in a derived class [child class]. You can override the functionality of a base class method to create the same name method with the same signature in a derived class. You can achieve method overriding using inheritance. Virtual and Override keywords are used to achieve method overriding.

class BaseClass  
    {  
        public virtual void Add(int num1, int num2)  
        {  
           // your logic will be here 
        }  
    }  
    class ChildClass: BaseClass  
    {  
        public override void Add(int num1, int num2)  
        {  
          // your logic will be here
            ;  
        }  
    }  
    class Program  
    {  
        static void Main(Args _args)  
        {  
            BaseClass baseClassObj;  
            baseClassObj = new BaseClass();  
            Info("Base class method Add :" + baseClassObj.Add(-3, 8));  
            baseClassObj = new ChildClass();  
            Info("Child class method Add :" + baseClassObj.Add(-2, 2));  
          
        }  
    }  

In the above example, I have created two same name methods in the BaseClass as well as in the child class. When you call the BaseClass Add method with less than zero value as parameters then it adds successfully. But when you call the ChildClass Add method with less than zero value then it checks for a negative value. And the passing values are negative then it asks for a new value.
 
So, here it is clear that we can modify the base class methods in derived classes.
 
Points to be remembered,
The method cannot be private.
The only abstract or virtual method can be overridden.
Which method should be called is decided at run time.

Sunday, November 7, 2021

Define Concept of Extensions

 An extension is a way to add functionality to an object in D365FO without modifying the base code of that object.  

Your extensions are compiled into their own DLLs, which are separate from the D365 base system libraries. It also makes it easier for Microsoft to patch their sys layer code.

Microsoft has added to allow customizations without allowing the base code to be changed because they plan to not allow any overlaying of SYS layer code.

Reference

Difference between Container, List, Map and Set

 Containers:

Containers are dynamic and have no limits. They can contain elements of

almost all data types: boolean, integer, real, date, string, container,

arrays, tables, and extended data types. However, objects may not be stored

in containers.

Containers in AX are used very often. It’s easy to work with them. But…

data in containers are stored sequentially and thus retrieved sequentially.

This means that containers provide slower data access if you are working with

_large numbers_ of records. In case of large numbers of records use temporary

tables.


List:

Lists are structures that may contain any number of elements that are

accessed sequentially. Lists may contain values of any X++ type. All the

values in the list must be of __the same__(this is the main difference

between lists and containers) type, given in the creation of the list. The

implementation of lists is such that the traversal of the list elements is __very

fast.

Take a look for example at the class Dialog addControl() method.

Their controls are stored in ctrls List.


Map:

A map is a data type that associates one (key) value with another value [An

analog – a small table in memory with two fields: Keys, Values]. Both the key

and value values may be of any valid X++ type, including objects. The types

of the key and the value are given in the declaration of the map. The

implementation of maps is such that access to the values is _very fast_.

Don’t confuse map X++ types with Map objects in AOT, which are used for

mapping tables with similar structures of fields


Set:

The functionality of Sets is similar to the list.  A Set is just an unordered list of items, while a list of items held by a Map

are indexed via a key.

Take look at

\Classes\sysLabel\LabelModuleId()

How to get label, name and data type of all fields of any table

 static void JobTableLabel(Args _args)

{


    DictTable       dt=new SysDictTable(tableNum(HcmWorker));

    FieldId       _fieldId=  dt.fieldNext(0);

    DictField     _dictField;

    

while(_fieldId)

    {

      _dictField  =dt.fieldObject(_fieldId);

 info(strFmt("Field Name %1 , Field Lable %2 and Field Type %3", _dictField.name(),_dictField.label(),_dictField.type()));

     _fieldId=  dt.fieldNext(_fieldId);

    }

}

BYOD (Bring your own database) in D365 FO



What is BYOD?

BYOD feature lets administrators configure their own database, and then export one or more data entities that are available in Finance and Operations into it.

The BYOD feature allows you to push data into a database you manage on Azure or on-premises.

This is done with the use of data entities. This means you can use existing entities or build your own entities to structure the data you need for your external database. Currently, more than 1700 Data entities are available.


Objective

You have data in D365 running in the cloud but you still have other applications that you run on-premise or elsewhere. 

So you need to get data from D365 into another environment so other applications can use the data. 

The most common use of BYOD is for data analysis and long-running reporting (Long-running reports are the pain point of AX)


Reference

Link

How-to search system logs for BYOD (and other) errors in D365 F&O : Link

Create DB > Configuration > Publish : Link

How to override form control Lookup using extensions in D365 FO

In D365FO we have a bunch of events to subscribe to on a form control level:

right-click on lookup event of control to subscribe to the event and paste in class.


[FormControlEventHandler(formControlStr(PayrollEmployerTaxRegion, Overview_StateId), FormControlEventType::Lookup)]

    public static void Overview_StateId_OnLookup(FormControl sender, FormControlEventArgs e)

    {

                  // Logic here

    }



Now to cancel parent event, D365FO provide a class FormControlCancelableSuperEventArgs


You can cancel the parent(Original event with below code)


        FormControlCancelableSuperEventArgs ce = e as FormControlCancelableSuperEventArgs;


        //cancel super() to prevent error.

        ce.CancelSuperCall();





//Code

[FormControlEventHandler(formControlStr(PayrollEmployerTaxRegion, Overview_StateId), FormControlEventType::Lookup)]

    public static void Overview_StateId_OnLookup(FormControl sender, FormControlEventArgs e)

    {

        SysTableLookup      sysTableLookup  = SysTableLookup::newParameters(tableNum(LogisticsAddressState), sender);

        Query               query           = new Query();


        // Filter lookup to only show US states

        query.addDataSource(tableNum(LogisticsAddressState)).addRange(fieldNum(LogisticsAddressState, CountryRegionId)).value(LogisticsAddressCountryRegion::findByISOCode(SysCountryRegionCode::countryInfo(curext())).CountryRegionId);


        // Sort the lookup by state Id

        query.dataSourceTable(tableNum(LogisticsAddressState)).addOrderByField(fieldNum(LogisticsAddressState, StateId), SortOrder::Ascending);


        // Add fields

        sysTableLookup.addLookupfield(fieldNum(LogisticsAddressState, StateId));

        sysTableLookup.addLookupfield(fieldNum(LogisticsAddressState, Name));


        // Run lookup

        sysTableLookup.parmQuery(query);

        sysTableLookup.performFormLookup();

        FormControlCancelableSuperEventArgs ce = e as FormControlCancelableSuperEventArgs;


        //cancel super() to prevent error.

        ce.CancelSuperCall();

    } 

Reference

Monday, November 1, 2021

Get Number sequence by code in D365 FO

NumberSeq   num;

        num = NumberSeq::newGetNum(NumberSeqReference::findReference(extendedTypeNum(DAPTransNum)));

info(num.num());

num.used();

Class basic code concept in D365 FO X++

Class GITS_Test_AY

{

    public static GITS_Test_AY construct()

    {

        return new GITS_Test_AY();

    }


    public void PrintName(str _Name)

    {

        info(strFmt("%1",_Name));

    }


    public static void withoutReference()

    {

        info(strFmt("Hello"));

    }


}






----------------Calling class----------------

class GITS_Runnable_AY

{

    public static void main(Args _args)

    {

        GITS_Test_AY    obj = GITS_Test_AY::construct();

        obj.PrintName("Jyoti");

        obj.PrintName("Atul");

        GITS_Test_AY::withoutReference();

    }


}

Difference between Index and Index hint

When you use the index keyword in a select statement the kernel will translate this to the "order by" command and the database optimizer will choose the best index to actually use. When you chose to use the index hint keyword in your select statement, Ax will force the database to use the chosen index.


Index:

When you use the index keyword in a select statement the kernel will translate this to order by command and the database optimizer will choose the best index to actually use. 

Example: select * from InventTable index GroupItemIdx will generate the following SQL statement to the database:

SELECT A.ITEMGROUPID, A.ITEMID, A.ITEMNAME,.... FROM INVENTTABLE A ORDER BY A.ITEMGROUPID, A.ITEMID

The Index ItemGroupIdx of the InventTable exactly contains the two fields ItemGroupID and ItemId (in that order). Using "index", you still give the control of which index to use to the database optimizer. So, if the optimizer finds a better index to use, it will use it.

Index hint:

When you chose to use the index hint keyword in your select statement, Ax will force the database to use the chosen index.

Example: select * from InventTable index hint GroupItemIdx will generate the following SQL statement to the database:

SELECT /*+ INDEX(A I_175GROUPITEMIDX) */ A.ITEMGROUPID, A.ITEMID, A.ITEMNAME,.... FROM INVENTTABLE A

Using "index hint", you take away the control of which index to use from the database optimizer. So, if there may be a better index, the database will not use it.