Tuesday, 17 December 2013

Table Inheritance

-> New Enhancement in  AX 2012
-> Table inheritance is a concept—facilitated through data modeling—that recognizes and represents generalized and specialized relationships between data entities. In Microsoft Dynamics AX 2012, tables can inherit, or extend, from the tables that are situated above them in a hierarchy. A base table contains fields that are common to all tables that derive from it. A derived table inherits these fields, but also contains fields that are unique to its purpose.
-> The support includes Field inheritance, table method inheritance, polymorphism, and casting between base and derived table buffers.
-> AX  2012 adopts table -per-type storage pattern to support this.
-> Converting a table inheritance record to a different type at run time is not allowing in AX.
-> After the inheritance relationships have been defined, certain table properties are disable on table inheritance tables,...
->  AX 2012 does not support creating table inheritance on either Inmemory or TempDB table types.



-> Advantages :
  i)  It simplified relational modeling , because AX data access stack recognizes the relations defined across the table inheritance and manages the stored data accordingly.


->  Create table inheritance Hierarchy

DD >> Tables, RC Table node, New Table.  ( property - SupportInheritance property - Yes )
 Do not create any field in table.

EX :


To create the table inheritance hierarchy
1. Launch the Microsoft Dynamics AX 2012 client in the development workspace.
2. In the AOT, navigate to Data Dictionary > Tables, and right-click the Tables node.
3. Click New Table. In the table property window, set the Name property value to ―Party‖ and set the SupportInheritance property to Yes. Do not create any field in the table. Save the table.
Note: Table inheritance properties such as Extends become enabled only if the SupportInheritance property has been set to Yes.
4. Repeat step 3 to create each of the other tables (Person, Organization, NonProfitOrganization, and GovernmentOrganization) in the mock party data model, setting the Name property value to the appropriate name each time.
5. Define the inheritance relationships on the tables as follows:
a. Select the Person table in the table property window, expand the drop-down list in the Extends property and select Party. Save the table.
b. Select the Organization table in the table property window, expand the drop-down list in the Extends property, and select Party. Save the table.
c. Select the NonProfitOrganization table in the table property window, expand the drop-down list in the Extends property, and select Organization. Save the table.
d. Select the GovernmentOrganization table in the table property window, expand the drop-down list in the Extends property, and select Organization. Save the table.
e. Leave the Extends property on the base table Party blank.
6. Create table fields according to the date model on the tables.
Note: Field names must be unique across the entire table inheritance hierarchy. This requirement ensures that the field name uniquely identifies the field across the hierarchy when appearing in system APIs that reference table fields. Developers will also notice that field IDs are unique across the entire table inheritance hierarchy.
7. Configure the type discriminator as follows:
a. Select the base table Party.
b. Create an int64 field and name it InstanceRelationType.
c. In the table property window, expand the drop-down list of the InstanceRelationType property, and select InstanceRelationType, as shown in the following illustration.
8. Optional: Complete this step only if you are displaying the instance type of the record on a form, and a report is needed.
Create a partyType enumeration type and define the elements, as shown in the following illustration.


Define an enumeration field of partyType on the Party base table. Name the field DisplayRelationType. Override the insert table method on the Party table.
public void insert()
{
DictEnum enumType = new DictEnum(enumnum(partytype));
int enumValue;
if (this.DisplayRelationType != partytype::Unknown)
{
return;
}
enumValue = enumType..symbol2Value(this.getInstanceRelationType());
if (enumValue == 255) // symbol2Value returns 255 if cannot convert
{
throw error(strfmt('No %1 enum element found for EnumValue %2',
enumstr(partytype),
this.getInstanceRelationType()));
}
else
{
this.DisplayRelationType = enumValue;
}
super();
}
9. Save and compile

- > Use Type Hierarchy browser , to visualize the table inheritance hierarchy.
RC AOT Tables node , >> Add Ins >> Type hierarchy browser .

-> Key Elements that influence the development and definition of a table inheritance hierarchy in AOT :
i) Abstract versus  Concrete : Abstract property - yes/No - Records can be created only for Concrete data types.
ii) Hierarchy properties
some properties are unabilable for NonProfitOrganization - SaveDataPerCompany, CacheLookup, ModifiedDateTime, ModifiedBy, ModifiedTransactionId, CreatedDateTime, CreatedBy, CreatedTransactionId, OccEnabled, EntityRelationshipType, InstanceRelationType, ValidTimeStateFieldType.

Table Methods :  Same support for table methods inheritance and polymorphism.
 There is no support for tables to implement interfaces.
 There is no support for specifying that a table is final (and therefore not subject to being overridden).
 If an incompatible method signature consisting of both the parameter types and the return type is specified on an overridden method (where the method name remains the same), the compiler will issue an error.

Relations on the table inheritance hierarchy :
Configuration Keys on the table inheritance hierarchy :
i) Can assign Configuration key at any level in the table inheritance hierarchy
ii) when table is assigned key , than all of its derived tables are assigned either the same key or one of its children keys in configuration key hierarchy.
iii) No key assigned , which makes table available during basic installation.
iv) When a table is disable by key, the entire derived branch of the table is disabled. Any data access activity on table will render no action from system.

Inserting Data in to the table inheritance hierarchy :
static void Job_InsertGovOrg(Args _args)
{
GovernmentOrganization tstGov;
NonProfitOrganization tstNpo;
tstNpo.Name = "Jaguar Concert Hall";
tstNpo.Email = "email@JaguarConcert.Org";
tstNpo.State = "IL";
tstNpo.City = "Urbana";
tstNpo.DunsNumber = " JagCont001";
tstNpo.NumberOfEmployees = 10;
tstNpo.AnnualContribution = 12345.67;
tstNPO.insert();
tstGov.Name = "Illinois State Tax Authority";
TstGov.Email = "Tax@il.gov";
tstGov.State = "IL";
tstGov.City = "Springfield";
tstGov.DunsNumber = "ILTAX001";
tstGov.NumberOfEmployees = 200;
tstGov.AgencyDescription = "Illinois State Tax Authority";
tstGov.insert();
info(tstGov.getInstanceRelationType()); //GovermentOrganization
}

Updating data on the Table inheritance hierarchy :
static void UpdateOrg(Args _args)
{
Organization tstOrg;
NonProfitOrganization tstNpo;
ttsBegin;
while select forupdate * from tstOrg
{
tstOrg.State = "IL";
tstOrg.NumberOfEmployees = tstOrg.NumberOfEmployees+10;
tstOrg.update();
}
select forUpdate * from tstNpo;
tstNpo.AnnualContribution = 76543.21;
tstNpo.update();
ttsCommit;
}
Deleting Data from the table inheritance hierarchy :
static void DeleteOrg(Args _args)
{
Organization tstOrg;
ttsBegin;
while select forupdate * from tstOrg
{
tstOrg.delete();
}
ttsCommit;
}

All Organization, Non-ProfitOrganization, Government Organization tables will be empty.
As Party table does not contain any records of Organization and its derived types, and therefore is not affected.

Invoking Table methods and table buffer Casting :
public void JustSayHello() //GovernmentOrganization
{
info("Hello GovernmentOrganization");
super();
}


public void JustSayHello() //Organization
{
info("Hello Organization");
super();
}


public void JustSayHello() //Party
{
info("Hello Party");
}
The super() keyword instructs the runtime to invoke the overridden method on the nearest base table. It is important to include the call to super() in case the table trigger methods (insert, update, and delete) are to be overridden. This is because calls to super() inside the trigger methods on the root table would invoke the kernel implementation of data manipulation operations.

Table Method Inheritance :

static void TableMethodInheritance(Args _args)
{
NonProfitOrganization tstNpo;
select firstOnly tstNpo;
info(tstNpo.Name);
tstNpo.JustSayHello();
}
Running the TableMethodInheritance code will produce the results shown in Figure 5. Because we do not override the JustSayHello method on the NonProfitOrganization table but only on the Organization and Party, calling JustSayHello on the NonProfitOrganization table buffer invokes the JustSayHello method defined on Organization and Party sequentially, as chained upwards by the super() calls

o/p :
Jaguar Concert Hall
Hello Organization
Hello Party

Table Method Polymorphism :

static void PolymorphismAndDownCast(Args _args)
{
Party tstParty;
GovernmentOrganization tstGov;
while select tstParty
{
info(tstParty.name);
tstParty.JustSayHello(); //polymorphism
if(tstParty is GovernmentOrganization) //downCast
{
tstGov = tstParty as GovernmentOrganization;
info(tstGov.AgencyDescription);
}
info(" ");
}
}

It shows that the NonProfitOrganization JustSayHello method and GovernmentOrganization JustSayHello method are invoked from the while select loop, as is demonstrated by the type of record instances retrieved.
Downcasting is necessary when you need to access the fields defined on derived types. The code sample also demonstrates the preferred way of downcasting from a base type table buffer to the derived type table buffer using the is and as operators


Querying data from a table inheritance hierarchy :

The following code example demonstrates querying customers that are of type NonProfitOrganization in the mock party model by using the X++ select statement.
static void SelectCustomer(Args _args)
{
NonProfitOrganization npo;
Customer cust;
while select firstonly * from npo join cust
order by npo.Name
where
Cust.party == npo.recid
&& npo.NumberOfEmployees>100
&& npo.state == 'IL'
{
info(cust.AccountNumber);
info(npo.Name);
}

}

The Customer table schema has a foreign key relationship to the Party table,

Customer table >> Realtions >> Party (Customer.Party == Party.Recid)

AX supports OrderBy, GroupBy, Having ... with Inherited fields
select * from Organization join customer
order by Organization.Name, organization(nonProfitOrganization.AnnualContribution)
where
Customer.party == Organization.recid
&& Organization.state == 'IL'




We can create View with the Tables with Table Inheritance :

CREATE VIEW "DBO".viewoforganizations AS SELECT t1.dunsnumber AS dunsnumber, t1.recid AS recid FROM organization t1

Support for Caching :

AX does not support entire table caching on the table inheritance hierarchy when record - level caching is suppported. Record - level caching for a table inheritance hierarchy is enabled by setting the CacheLookup table property value on the root table of the hierarchy .

Create a polymorphic form :
Adding DS Organization :

Inherited fields from Party base table are automatically populated under the fields node , 2 DS Organization _NonProfitOrganization and organization_GovernementOrganization, are automatically created .









No comments:

Post a Comment