Thursday, 22 November 2012

How to open a form in runtime in Ax 2012

Hi Friends,

Today we are going to open a form in runtime in Ax 2012.

There are two ways of opening a form in runtime in Ax 2012.
Below given codes are for just example.

The first type of opening a form is given below

client static Object OpenToolBar()
{
Object toolBarForm = null;
Args args = new Args();
;
args.name(formStr(formName));
toolBarForm = classFactory.formRunClass(args);
toolBarForm.init();
toolBarForm.run();
toolBarForm.detach();
return toolBarForm;
}

The second type is given below

client static Object getToolBarObject()
{
ObjectIdent objIdent = infolog.globalCache().get(formStr(formname),null,null);
Object toolBarForm = objIdent ? objIdent.object() : null;
;
if(!toolBarForm)
{
toolBarForm = S3SecurityToolBarOpen::OpenToolBar();
}
else
toolBarForm.setActive();

return toolBarForm;
}

Vivek Chirumamilla

Tuesday, 20 November 2012

Dict Class in Ax 2012

Hi Friends,

Today we will have a slight introduction to dictclass .

DictClass have wide vaiety of operations one of them is call Object.

We have created a object for PurchFormLetter_Invoiced() and call the method called missingnumber in the class.

The output of the class is printed at the end of section.

static void Job_Example_DictClass_CallObject(Args _args)
{
DictClass dictClass;
anytype retVal;
str resultOutput;
PurchFormLetter_Invoice p = new PurchFormLetter_Invoice();
ExecutePermission perm;

perm = new ExecutePermission();

// Grants permission to execute the DictClass.callObject method.
// DictClass.callObject runs under code access security.
perm.assert();

dictClass = new DictClass(classidget(p));
if (dictClass != null)
{
retVal = dictClass.callObject("missingNumber", p);
resultOutput = strfmt("Return value is %1", retVal);
print resultOutput;
pause;
}

// Closes the code access permission scope.
CodeAccessPermission::revertAssert();
}

Vivek Chirumamilla

Security Policy property in Ax 2012


Hi Friends,

I have been working on the security . I have came across the property of ContextType and ContextString.

I will to explian ContextType and ContextString properties.

In ContextType LookUp there will be three values they are

1.ContextString

2.RoleName

3.RoleProperty.

Here don't get confused with the ContextString in LookUp and ContextString in Properties.

They both are related to each other.

Case 1: When ContextType property is set to "ContextString"

The ContextString property is empty. This combination implies that when it is enabled, this security policy will always be applicable for all users.

Case 2: When ContextType property is set to "RoleName"

The RoleName Property will be enabled and it shows roles select the appropriate Role for the situation.The Role which is activated for the user the security policy applies.

Case 3: When ContextType property is set to "RoleProperty"

The RoleProperty is the combination of ContextString and RoleName. So both the properties will be activated.

I hope you have understood the concept of ContextType property in Security Policy.



Vivek Chirumamilla

Find All Fields that user cannot access in Ax 2012

Hi Friends,

Note:: The program given below is a sample program and it cannot be used in real scenarios in Ax 2012.

Today we will have a small program in Ax 2012 that is used to find out how many tables and how may field in the tables the security keys are attached and find out which keys there will be security for that.

Here is the program which I have been talking about-----

static void GmTrimAccessFieldScan(Args _args)
{
// Edit the following three macro values to your needs. For example:
// ** Start: with a table whose name starts with an 'A'.
// ** Stop: with a table whose name starts with a 'Z'.
#define.SearchTableNameRangeStart("")
#define.SearchTableNameRangeStop("")
#define.TargetTableNameLikeFilter("*")

TreeNode tnTable,
tnField;
str sTableAosAuth,
sFieldAosAuth;
int nCountOfTpfTablesFound = 0,
nCountOfAotTables = 0,
nCountOfTrimmedFields = 0;

// Establish start node among the table nodes.
if (#SearchTableNameRangeStart == "")
{
tnTable = TreeNode::findNode
("\\Data Dictionary\\Tables").AOTfirstChild();
}
else
{
tnTable = TreeNode::findNode
("\\Data Dictionary\\Tables\\" + #SearchTableNameRangeStart);
}


while (true)
{
nCountOfAotTables++;
// Provide ongoing progress reports.
if ((nCountOfAotTables MOD 50) == 3)
{
print int2Str(nCountOfAotTables)
+ " tables examined so far, at " + tnTable.AOTname();
print int2Str(nCountOfTpfTablesFound) + " TPF okay tables found so far.";
print int2Str(nCountOfTrimmedFields) + " trimmed fields found so far.";
print "---------------- Wait...";
}
// Perhaps stop before the end of the AOT, for convenience.
if (#SearchTableNameRangeStop < tnTable.AOTname() &&
#SearchTableNameRangeStop != ""
)
{
break;
}

// Apply the table name wild card filter.
if (tnTable.AOTname() like #TargetTableNameLikeFilter)
{
sTableAosAuth = tnTable.AOTgetProperty('AOSAuthorization');
// Test whether there is authority to access the table, under TPF.
if (sTableAosAuth != 'None')
{
nCountOfTpfTablesFound++;
// Loop through the fields on this table.
for (tnField = TreeNode::findNode
('\\Data Dictionary\\Tables\\'
+ tnTable.AOTname()
+ '\\Fields').AOTfirstChild();
tnField;
tnField = tnField.AOTnextSibling()
)
{
sFieldAosAuth = tnField.AOTgetProperty('AOSAuthorization');
// Test whether there is authority to access the field.
if (sFieldAosAuth != 'No')
{
nCountOfTrimmedFields++;
info(strFmt('%1 %2 is a trimmed field that you cannot access.',
tnTable.AOTname(), tnField.AOTname()));
}
} // for each field in AOT
} // if table is guarded by the Table Protection Framework (TPF).
} // name is Like

// Prepare for next interation of this loop.
tnTable = tnTable.AOTnextSibling();
if (tnTable == null) break;

} // for each table in AOT

print "-------- Final Report (see also the Infolog) --------";
print int2Str(nCountOfAotTables)
+ " tables examined so far, at end.";
print int2Str(nCountOfTpfTablesFound) + " TPF tables found so far, at end.";
print int2Str(nCountOfTrimmedFields) + " trimmed fields found so far, at end.";
print "-------- Done. --------";
pause;
}



Vivek Chirumamilla

Friday, 26 October 2012

Date Conversion to string in Ax 2012

Hi Friends,

Today we will have a look at the date values and its conversion to string values in Ax 2012.

For Eg: We have a variable called Date d

We have assigned a value to it d = 20/07/1988



str Date2StrEasyLocal(date _date)
{
return ( date2Str
(_date,
321, // YMD
DateDay::Digits2,
DateSeparator::Hyphen,
DateMonth::Digits2,
DateSeparator::Hyphen,
DateYear::Digits4) );
}


str s = Date2StrEasyLocal(d);

By the above way we can covert the dates in string values.

Vivek Chirumamilla

Tuesday, 2 October 2012

Other Databse Connection using Ax 2009

hi friends,

Connection with other database can be established from Ax.

This database may not have connection with the database you are using.

By using ODBCConnetion(Other DataBase Connection) you can use it.

I have given a sample code and example of it.

static void dbODBCConnection(Args _args)
{
LoginProperty loginProp;
ODBCConnection conn;
Resultset resultSet, resultSetCount;
Statement statement1, statement2;
;

loginProp = new LoginProperty();
loginProp.setServer('172.16.0.999');
loginProp.setDatabase('AxDynamics2009RND');


conn = new ODBCConnection(loginProp);

statement1 = conn.createStatement();
resultSet = statement1.executeQuery("SELECT * from Attandance");

while (resultSet.next())
{
info(resultSet.getString(2));
}
}


happy daxing,

Vivek Chirumamilla

Thursday, 14 June 2012

How dates are converted to string in Ax 2009

Hi friends

Today we are going to convert dates in Ax 2009. Below I am going to publish a simple program for that . Paste the following program in Job and go through it.
Display str balanceDate()
{
str day;
str month;
str currentYear;

str datevalue;
int i;
transdate StartMonth;
str year_format;
;
if(salarymonth)
{
StartMonth = Global::dateStartMth(salarymonth);
day = int2str(dayofMth(any2date(StartMonth)));
month = substr(mthname(mthofyr(any2date(StartMonth))),1,3);
currentYear = int2str(year(any2date(StartMonth)));
year_format = substr(currentYear,3,2);
for(i=1; i<=3; i++)
{
switch(i)
{
case 1:
datevalue += day ;
datevalue += ' ';
break;
case 2 :
datevalue += month;
datevalue += ' ';
break;
case 3:
datevalue += year_format;
break;

}
datevalue = datevalue;
}

}
return datevalue;
}

I hope after seeing the program you will understand a lot more about it.


Vivek Chirumamilla

Friday, 8 June 2012

Query using X++ in Ax 2009

Hi Friends,

You know queries are the most easier way to work on than any other statements .

You can derive complex syntax easily by using query.

For first giving us a clear idea we are not going too much deep into the query.

First we have to declare a query by using the following syntax

Query q = new Query();

And we need the following declarations to add datasource, range and to run the query

QueryBuildDataSource qbds;

QueryBuildRange qbr;

QueryRun queryRun;

qbds= q.addDataSource(tablenum(InventTable));
qbds.addSortField(fieldnum(InventTable,ItemId));
qbr = qbds.addRange(fieldnum(InventTable,ItemId));
qbr.value("1104");
qbr1 = qbds.addRange(fieldnum(InventTable,DataAreaId));
qbr1.value(strfmt('(((%3.FromDate >= %1) || (%3.Todate > %1)) && ((%3.Todate<=%2) || (%3.Fromdate<%2)))',Date2StrXpp(LeaveFromDate),
Date2StrXpp(LeaveToDate), q.dataSourceTable(tablenum(InventTable)).name()));

queryRun = new QueryRun(q);
while (queryRun1.next())
{
InventTable= queryRun.get(TableNum(InventTable));

info(strfmt("%1" ,InventTable.ItemId));
}

Vivek Chirumamilla

Thursday, 7 June 2012

date,month tips in Ax 2009

Hi Friends,

Today we are going to have tips on month values and how to effectively use them in Ax 2009.

Here are some tips to use::

To get the next month value use "nextMth(Month)"

To get the previous month value use "prevMth(Month)"

To get the stating month date if the value of a month date is in middle use "datestartmth(Month)"

To get the end month date if the value of a month date is in middle use "dateendmth(Month)"



Vivek Chirumamilla

Tuesday, 5 June 2012

Calender Update in Ax 2009

Hi friends,

There is a job which update Calender and calender working times.

Below is the job run while updating calender.

static void workCalendarUpdateJob(Args _args)
{
WorkCalendarDate WorkCalendarDate;
;
ttsbegin;
update_recordset WorkCalendarDate
setting WorkTimeControl = WorkTimeControl::Open
where WorkCalendarDate.CalendarId == "CalenderName";
ttscommit;
}


Vivek Chirumamilla

To resolve unbalanced X++ TTSBegin/TTSCommit pair in Ax 2009

Hi friends,

I have an unbalanced X++ TTSBegin/TTSCommit pair has been detected .Cause of this include (a) too many/few TTSBegin or TTS Commit . The current TTS level is '1'

To solve this error there is a job which is to be executed when yo get this error.

static void resetTTS(Args _args)
{
while (appl.ttsLevel() > 0)
ttsAbort;
}



Vivek Chirumamilla

Thursday, 31 May 2012

Installing Workflow in Ax 2009

Hi friends,

Today we are going to install the workflow and configure it in AX 2009

Open Administration => Security => SystemServiceAccounts.

In System service Accounts you will find alias Name(Proxy Account) and Network Domain.Enter Workflow system Account and

Workflow Execution Account.

Note : Have Admin rights before installing workflow

1. Install the workflow as per the wizard

2.It will ask for .Net Business Connector Proxy Account password.

3.After that it will ask credentials for either put proxy account it is in another network put Domain\computerName$

4.Finish the installation.

Here come the part of making the workflow Url valid.

1. Open IIS Manager settings.

2.If you install workflow in you will see the workflow installed in Default site.

Note :: If windows Share point servives or share point server is running on the site then workflow cannot execute in that port.

You have to create a new website and new port and add an exception to the port.

3. In Application pool => click Advanced settings keep the following properties

.NetFrameWork = 2.0

Enable32BitApplications => true

4. In Defalut website click MicrosoftSynamicsAXWorkflow50

Authentication => AnonymousAuthentication => Enabled and click edit and keep AppPoolIdentity to everyone(:: error 401)

Directory Browsing => enable it (::error 405)


5. Check whether the workflow is running correctly or not by browsing.

6. In Administration => setup => workflowInfastructureAndConfiurationWizard run it and define the workflow group and set the

time interval for it.

By this workflow is ready to use .

Vivek Chirumamilla

Sunday, 27 May 2012

Adding a range in Data Set in AX 2009

Hi friends,

Today we are going to add range in a Dataset.

A data set, typically used to access data for Enterprise Portal, can have one or more data sources from which data is accessed. You can use X++ code to add a range that restricts the data that is accessed by the data source. The code that adds the range must be written correctly so that only the data in the range is accessed.

Adding a Range:

To add a range for the data source that is used by a data set, you must override the init method for the data source. In this method, create a QueryBuildRange object that defines the range and specifies the values allowed. To prevent the range from being changed or removed, set the range status to hidden. This last step is very important to prevent data outside the range from being accessed.

The following example sets a range for the ContactPerson data source in the EPCustTableInfo data set. The range prevents rows from being accessed that have empty values in the ContactPerson or CustAccount fields. The status of the range is set to hidden to make sure that the range cannot be changed or deleted.

public void init()
{
QueryBuildRange rangeCustAccount;
super();

rangeCustAccount = this.query().dataSourceTable(tablenum(ContactPerson)).addRange(fieldnum(ContactPerson, CustAccount));
rangeCustAccount.value(SysQuery::valueNotEmptyString());
rangeCustAccount.status(RangeStatus::Hidden);
}





Vivek Chirumamilla

Wednesday, 23 May 2012

Inventory Dimensions In Ax 2012

Hi friends,

Today we have Inventory Dimensions

Inventory Dimensions are classified into 3 groups

Product :: Color,Size,Configuration.

Storage :: Site, Warehouse,Location,Pallet Id.

Tracking :: Batch number , Serial number.

The Configuration technology field specifies which type of product configuration, if any, will be applied to the newly created product.

Predefined variant - This type should be chosen if the product will not be configured, but simply rely on the user’s choice of Color, and/or Size, and/or Configuration for each transaction

Dimension-based configuration - This type should be chosen if the user will build a configurable BOM that relies on configuration rules to build the Config ID and the BOM lines. (This technology may only be chosen if Configuration is active on the Product dimension group selected for the product)

Rule-based configuration - This type should be chosen if the product will use Product builder

Constraint-based configuration - This type should be chosen if the product will use the new AX 2009 Constraint based product configuration method. (This technology may only be chosen if Configuration is active and is the lone Product dimension active for the Product dimension group selected for the product)

In Ax 2012 we have two types of items Products and product Masters, Product dimension group can only be selected to Product Masters.

Product Dimensions:

Navigate to Product information management -> Setup -> Dimension groups -> Product dimension groups.

Click on ‘Active’ check box beside the Product dimension you want to as shown in the above figure to activate the Product Dimensions

Storage Dimensions:

Navigate to Product information management -> Setup -> Dimension groups -> Storage dimension groups.

To make Site a mandatory, then select Mandatory check box.

· To make Primary stocking active for Sitethen select the ‘Primary stocking’ check box.

· To activate a dimension select ‘Active’ check box for that particular dimension.

Tracking Dimensions:

Navigate to Product information management -> Setup -> Dimension groups -> Tracking dimension groups.

To activate serial number control (a unique serial number can only be entered) select ‘Serial number control’ check box.


Assigning the Dimension groups to a new product of type Product Master:

To create a product for a single company or entity go to Product information management -> Common -> Released products.

· Click the Product -> New -> Product button.

To Assign Tracking and Storage Dimension Groups click the Product -> Set up -> Dimension group button.

To Assign Product dimensions

· As we have only selected Configurations and size in the Product Dimension Group, we can only see these two Dimensions in the Product Dimension form.

· Now click on ‘New’ Button to create a new configuration.

· Enter the Configuration and description of that particular configuration.

· Click on ‘size’ to create ‘Size’ dimension option

· Follow the same procedure followed for Configuration creation to create new ‘Sizes’.


Creating Product Variants::

· In AX 2009, there is a concept called Item Dimension combinations. An item must have item dimension combinations created in order to process items with item dimensions. The same concept is renamed as Product Variants in AX 2012.

· To create Product Variants for a product go to Released Product form ->Product Tab -> ‘Product master’ action group -> ‘Released product variants’ button.

· Clicking on the Variant suggestions button will show all the possible combinations of Configurations and Sizes.

· Click the Select all button to select all the combinations or else you can select required combinations and then click on Create button.

· All the Product Variants are created. Now Close the Released product variants form.




Vivek Chirumamilla

Monday, 21 May 2012

How to Add Dimension In Ax 2012


Hi friends ,

Today we are going to add dimension in Ax 2012

You can add dimensions to Microsoft Dynamics AX. The product ships with three dimensions: Department, Cost center, and Purpose.

Dimensions are based on extended data types that are defined as arrays. The extended data types with dimension information are as follows:

Dimension

DimensionAllocation

DimensionCriteria

DimensionKeepFromTransaction

DimensionLedgerJournal

MandatoryDimension


ADD A DIMENNSION::

1.In the Application Object Tree (AOT), add a new array element for the dimension to each extended data type listed above.


2.Associate the new array element with certain dimension table fields by doing the following for the Dimension and DimensionCriteria extended data types.

a.Click the extended data type, and then click the new array element.

b.Right-click Relations, and then click New > Normal to add a normal relation.

c.Right-click the relation, and then click Properties.

d.Set the Table property to Dimensions, and then set the RelatedField property to Num.

e.Right-click Relations, and then click New > Related field fixed to add a related field fixed relation.

f.Right-click the relation, and then click Properties.

g.Set the RelatedField property to DimensionCode.

3.Add a new value to the SysDimension enumeration that represents the new array element by doing the following.

a.Click Data Dictionary > Base Enums, right-click the SysDimension, and then click New Element.

b.Right-click the new element, click Properties, and then modify the Name property.

c.Modify other properties, as needed.

4.Create a relationship between the LedgerJournalTrans table and the Dimension table by doing the following.

a.Click Data Dictionary > Tables > LedgerJournalTrans, right-click Relations, and then click New Relation.

b.Right-click the new relation, and then click Properties.

c.Set the Table property to Dimensions, and set the Name property to InterCoDimension to distinguish it from other InterCoDimension relations on the LedgerJournalTrans table.

d.Add a related field fixed relation and two normal relations to the InterCoDimension relation, as shown in the following example.





5.Modify the LedgerAllocation form to display the new dimension by doing the following.

a.Right-click the LedgerAllocation form, and then click Compile.

b.Locate the following group controls in the TabPage:Dimension control, set the AutoDataGroup property for each group control to No, and then save the changes.

Group:FromDimensionNo

Group:SelectionCriterion

Group:To

Group:KeepTransactionDimension

The system automatically adds a new control to each group control that corresponds to the array element that you added to the extended data types in step 1.



Vivek Chirumamilla

Wednesday, 16 May 2012

Primary Index In Ax 2012

Hi friends,

A primary key is one type of key. The other type of key is an alternate key. There is a maximum of one primary key per table, whereas a table can have several alternate keys. The primary key is usually the type of key that other tables, called child tables, refer to when a foreign key field in those other tables need a relational identifier.

Starting in Microsoft Dynamics AX 2012 the primary key for every new table is always enforced by an index that has exactly one field. The one field is usually an incremented number or a completely meaningless number that is generated by the system. For new tables the default is a primary key based on the RecId field. This is represented as the surrogate key in the user interface.

The following describes the PrimaryIndex property and other that are related to keys.



PrimaryIndex

The drop-down list contains the surrogate key plus every index on the table that has its AlternateKey property set to Yes.

Vivek Chirumamilla

Sunday, 13 May 2012

Dynamics AX Caching in Ax 2009

Cache Location

Caches are used on both the client and the server. The Microsoft Dynamics AX runtime manages the cache by removing old records when new records are added to the cache.

Client Cache

A client-side cache can be used only by the client. The client cache is used when a select is executed from the client tier. If no record is found in the client cache, the client then searches the server cache for the record. If the record isn't located in the server cache, it's retrieved from the database. The maximum number of records maintained in a client cache is 100 records per table for a given company.

Server Cache

A server-side cache can be used by any connection to the server. The server cache is used when a select is executed on the server tier. If no record is found in the cache, it's retrieved from the database. The maximum number of records maintained in a server cache is 2,000 records per table for a given company.

Record Caching

Microsoft Dynamics AX database record caching is a performance-enhancing feature that helps avoid database access when it's not strictly necessary. Retrieving database records from memory instead of the database significantly speeds up data access. Caching can reduce the performance penalty for repetitively accessing the same database records.

Types of Caching

Caching is transparent to the application; however, it's important to know how caching works to optimize its performance in Microsoft Dynamics AX. Following are the types of caching:

Single-record
Set-based
Single-record caching has the following characteristics:

Defined at design time
Moves records to the cache based on the table's CacheLookup property and the type of SELECT statement that is used to retrieve the record


Set-based caching has the following characteristics:

Defined either at design time or in X++ code
Moves sets of records to the cache
Implemented either through the table's CacheLookup property or in code by using the RecordViewCache class
Single-Record Caching

Record caching is enabled for a table when all the following statements are true:

The CacheLookup property on the table is enabled by setting it to one of the following values:
· notInTTS
· Found
· FoundAndEmpty

The table's PrimaryIndex property is set to a unique index that exists on the table. The RecId index does not qualify as a caching index unless you set the table's PrimaryIndex property to this index.
The record buffer disableCache method has not been called with a parameter of true.
The fields in the table's unique index make up the caching key. A record is placed in the cache when the following criteria are met:

The table is cached by setting the CacheLookup property to notInTTS, Found, or FoundAndEmpty.
The SELECT statement that selects the records uses an equal operator (==) on the caching key. The fields in the WHERE clause of the SELECT statement match the fields in the index referenced by the table's PrimaryIndex property.
The table's CacheLookup property defines how and when records are cached as shown in the following table.

CacheLookup Property Value

None

No data is cached or retrieved from the cache for this table.
This property value should be used for tables that are heavily updated or where it's unacceptable to read outdated data.
NotInTTS

All successful caching key selects are cached.
When in a transaction (after ttsBegin), no caches made outside the transaction are used. When inside a transaction, the record is read once from database and subsequently from cache. The record is select-locked when read in a transaction, which ensures that the record cached is not updated while the transaction is active.
A typical example of the NotInTTS property is the CustTable in the Microsoft Dynamics AX standard application. It's acceptable to read outdated data from the cache outside a transaction, but when data is used for validation or creating references, it is ensured that the data is real-time.
Found

All successful caching key selects are cached. All caching key selects are returned from the cache if the record exists there. A selectforUpdate in a transaction forces reading from the database and replaces the record in the cache.
This is typically used for static (lookup) tables, such as Unit, where the record usually exists.
FoundAndEmpty

All selects on caching keys are cached, including selects that are not returning data.
All caching key selects are returned from caching if the record exists there, or the record is marked as nonexistent in the cache. A selectforUpdate in a transaction forces reading from the database and replaces the record in the cache.
An example of FoundAndEmpty record caching is in the Discount table in the Microsoft Dynamics AX standard application. By default, the Discount table has no records. By using a FoundAndEmpty cache on this table, the keys that are queried for but not found are stored in the cache. Subsequent queries for these same non-existent records can be answered from the cache without a round trip to the database.
EntireTable

Creates a set-based cache on the server. The entire table is cached as soon as at least one record is selected from the table.


The Found and FoundAndEmpty caches cross transaction boundaries. The NotInTTS cache is newly created inside a transaction. This example, modified for the purposes of this topic, demonstrates how records are retrieved from the cache when the table's CacheLookup property is set to NotInTTS, and the PrimaryIndex property is set to a unique index on the AccountNum field.

static void NotInTTSCache(Args _args)
{
CustTable custTable;
;
// The query looks for records in the cache.
// If records don't exist, the query accesses the database.
select custTable
where custTable.AccountNum == '4000';
// The transaction starts.
ttsbegin;
// The cache is not used. The query accesses the database
// and records are placed in the cache.
select custTable
where custTable.AccountNum == '4000';

// The query uses the database because
// the forupdate keyword is used.
select forupdate custTable
where custTable.AccountNum == '4000';
// The query uses the cache and not the database.
select custTable
where custTable.AccountNum == '4000';
// The query uses the cache because
// the forupdate keyword was used previously.
select forupdate custTable
where custTable.AccountNum == '4000';

// The transaction is committed.
ttscommit;

// The query will use the cache.
select custTable
where custTable.AccountNum == '4000';
}
If the table CacheLookup property was set to Found or FoundAndEmpty, the first select statement inside the transaction (after the TTSBegin statement) would retrieve the record from the cache.

Set-Based Caching

In Microsoft Dynamics AX, groups of records can be cached all at once with set-based caching. Set-based caching can be implemented in two ways:

At design time, by setting the table's CacheLookup property to EntireTable.
In code, by using the RecordViewCache class.

EntireTable Cache

When you set a table's CacheLookup property to EntireTable, all the records in the table are placed in the cache after the first select. This type of caching follows the rules of single record caching in which the SELECT statement WHERE clause fields must match those of the unique index defined in the table's PrimaryIndex property.

The EntireTable cache is located on the server and is shared by all connections to the Application Object Server (AOS). If a select is made on the client tier to a table that is EntireTable cached, it first looks in its own cache and then searches the server-side EntireTable cache. An EntireTable cache is created for each table for a given company. If you have two selects on the same table for different companies the entire table is cached twice.

Joins that include an EntireTable cached table are only performed against the cached copy when all tables participating in the join are EntireTable cached. Otherwise a database join is performed.

Important Note:

Avoid using EntireTable caches for large tables because once the cache size reaches 128 KB the cache is moved from memory to disk. A disk search is much slower than an in-memory search.

Flushing the Cache

An EntireTable cache is flushed whenever an insert, update, or delete is made to the table. At the same time, the AOS notifies other AOSs that their caches of the same table must be flushed. After the cache is flushed, a subsequent select on the table causes the entire table to be cached again. Therefore, avoid caching any table that's frequently updated. Regardless of when updates are made, EntireTable caches are flushed every 24 hours by the AOS.

RecordViewCache Cache

Set-based caching is implemented in code by using the RecordViewCache class. You must first create a record buffer using the nofetch statement and then pass the record buffer to the RecordViewCache class when it's instantiated.

The cache is created on the server and is only accessible by the process that creates the cache object. Once the cache is instantiated, all select statements are issued against the cache, as shown in the following

static void RecordViewCache(Args _args)
{
CustTrans custTrans;
RecordViewCache recordViewCache;
;
// Define records to cache.
select nofetch custTrans
where custTrans.AccountNum == '4000';

// Cache the records.
recordViewCache = new RecordViewCache(custTrans);

// Use cache.
select firstonly custTrans
where custTrans.AccountNum == '4000' &&
custTrans.CurrencyCode == 'USD';
}


Due to concurrency issues, the forUpdate keyword on the instantiating X++ SELECT statement should only be used when all of the records in the result set will be updated. Otherwise it's a better strategy to use select forUpdate only for the records that are to be updated.

The RecordViewCache class is used in a select when the select is from a table that's cached, the select statement doesn't participate in a join and the select WHERE clause matches the WHERE clause with which the RecordViewCache was instantiated.

The cache created by the RecordViewCache class stores records in a linked list. Therefore Microsoft Dynamics AX searches the cache sequentially for records that match the search criteria. If the SELECT statement contains an ORDER BY clause, a temporary index is placed on the cache and the runtime uses the index when searching records.





Vivek Chirumamilla

Wednesday, 9 May 2012

Cross Comapany support in Ax 2009

Hi friends,

Today we have cross company support functionality published in the below post

static void Test(Args _args)
{
InventTable inventTable,inventTable1;

str Item;

str ItemName;

int ItemInt,ItemInt1,value,i;

container conCompanies = [ 'CEU', 'CEE' ];
;

select firstonly ItemId from inventTable1 order by ItemId;
Item = inventTable1.ItemId;


// While select ItemId from inventTable order by ItemId
while select
crossCompany
: conCompanies
ItemId from inventTable
order by dataAreaId,inventTable.ItemId
{

ItemName = inventTable.ItemId;

if(Item != ItemName)
{

ItemInt = str2int(ItemName);

ItemInt1= str2int(Item);

value = ItemInt - ItemInt1;

for(i=1;i {
ItemInt1 = ItemInt1 + 1;
info(int2str(ItemInt1));
}
Item = inventTable.ItemId;
}

}

}

Vivek Chirumamilla

Thursday, 12 April 2012

Map & MapEnumerator Objects in Ax 2009

Hi friends, Today we are going to see about map and map enumerator . Maps are used to store the data just like temporary tables. It is much quicker than temporary tables. The critical difference is that even though Map resembles a table at first glance, it does not contain data but functions rather as a library of methods intended to be shared by several tables. Maps can be used in different locations , and you need to act on those values. Map Example:: Map M; ; M = new map(type::integer,type::integer); M.insert(custTable.RecId,custTable.custGroup); M.valueSet(); // Retrieving the values from the map M.exist(custTable.RecId); M.lookUp(CustTable.RecId); This is a wonderful way to look up the value because you have the exact key. What if you wanted to transverse or enumrate through a given map to act on each value. This would be similar to moving through a resultset, etc: MapEnumerator ME; ; ME = new MapEnumerator(M); while(ME.moveNext()) { // .. preform some logic .. } With this you can now walk through or enumrate through a given map and act upon each value stored in it. Like I said, Maps are very cool, easy to use, and much faster and preferred than using a temp table. Check back soon for more posting on code examples, how to's, etc. Vivek Chirumamilla

Sunday, 8 April 2012

Record Level Security in Ax 2009

Hi friends,

Today we are going to discuss Record Level Security in Ax 2009. Record level Security button is found in Administration => Setup => Security => RecordLevelSecurity

After that press Cntrl+N to create a record , the wizard will be opened. Click all the tables which you want to create record level security and finish it.

There will be a query button which you can add ranges to it.


This RLS is restricted to particular company only and the RLS is limited to particular group only .

Note :: To arrange restrictions on the particular group use SysQueryRangeUtil class.



Vivek Chirumamilla

Friday, 30 March 2012

Deleting duplicate records in Table through code in X++

Hi friends ,


We are going to see how to delete duplicate records on the Table through code by using X++


static void DeleteDuplicate(Args _args)
{
Set fieldset = new set(types::Integer);

// create dictindex from unique index

DictIndex dictIndex = new dictIndex (tablenum(PurchTable), indexnum(PurchTable,PurchIdx));

;

// these are fields from index

// add them to set

fieldset.add(fieldnum(PurchTable ,OrderAccount));

ReleaseUpdateDB::indexAllowDup(dictIndex);

// set allow duplicates

ReleaseUpdateDB::deleteDuplicatesUsingIds(tablenum(PurchTable),0,fieldset);

//reenable duplicates

ReleaseUpdateDB::indexAllowDup(dictIndex);

info("Deletion done");


}




Vivek Chirumamilla

Thursday, 15 March 2012

RunBaseBatch in Ax 2009

Hi Friends,

Today we are going to export data by using a class which extends from runbasebatch. The replica of it would be found in tutorial_runbasebatch . In administration module setup check the server configuration whether is batch server is checked or not. In same BatchGroup create your own batch group. In basic module Inquiries in Batch you can find whether its working or not. If you dont click the batch processing button to yes it will run instantly.

Note For giving the file name dynamically check the form tutorial_form_file.




Vivek Chirumamilla

Tuesday, 21 February 2012

Ax 2009 Finanace (pdf) document

Hi friends,

Today we have Finance document . Enjoy reading it


Finance
Vivek Chirumamilla

Ax 2009 Trade and Logistics second document

Hi friends,

Today we have trade and logistics 2 document

KYtT&L2

Vivek Chirumamilla

Ax 2009 Trade and Logistics document

Hi friends,

Here is the document of Trade and Logistics 1 st document.Enjoy reading
KytT&L1

Vivek Chirumamilla

Wednesday, 15 February 2012

Multiple values in a dialog field in Ax 2009


Hi Friends,
     
Object dialog()
{

Dialog                         dialog;
DialogField                fldDivision
FormStringControl   formStringCtrlDiv;
;

dialog = super();
dialog.addField(typeId(CNLIN_Division)) //Your EDT/field name
formStringCtrlDiv = fldDivision.fieldControl();
formStringCtrlDiv.replaceOnLookup(false);
return dialog;

}

Thursday, 19 January 2012

How to filter records in the form by code in Ax 2009

Hi friends we are going to filter the records in the form by using the code in Ax 2009
Step 1: Declare a class variable
In the ClassDeclaration method of the form, define a range.

QueryBuildRange CurrencyQBR;

Step 2: Instantiate the new range.
In the init method on the datasource of the form, you assign the range to a specific field (after the super call).

public void init()
{
super();

CurrencyQBR = this.query().dataSourceName('CustTable').addRange(fieldnum(CustTable,Currency));
}

Step 3: In the last step, you assign a value to the range.
This is done in the executeQuery method on the same datasource of the form. Before the super call. Like this:

public void executeQuery()
{ ;

CurrencyQBR.value(queryvalue('USD'));

super();
}

    By this you can filter record
                                                     Vivek Chirumamilla

Wednesday, 18 January 2012

Create a parameter Table in Ax 2009

Hi Friends,
    We have a small requirement of making a parameter Table to separate module. The basic of parameter table is found in this blog. We have a mandatory field named "key" which is of integer type.The properties of parameter table is as follows,
MaxAccessMode   Edit
CacheLookUP       Found
TableGroup           Parameter
And the properties of Key field is as follows
AllowEditOnCreate,AllowEdit, Visible is set to "NO"
The methods of find and exist are as follows,

static client server FleetParameters  find(boolean _forupdate = false)
{
    Parameters parameter;
    ;
        select firstonly parameter
            index Key
            where parameter.Key == 0;

        if (!parameter)
        {
            Company::createParameter(parameter);
            NumberSeqReference::construct(Parameters::numberSeqModule()).load();
        }
    return parameter;
}

exist

static boolean exist()
{
    return (select firstonly RecId from Parameters).RecId != 0;
}
And the update method of Table

void update()
{
    super();
    flush Parameters;
}
And Delete method of Table is overriden as

void delete()
{
    throw error("@SYS23721");
}
And a method called number sequence module is written as

static client server NumberSeqModule  numberSeqModule()
{
    return NumberSeqReference_VkFleet::numberSeqModule();
}

And then create a form parameters
And do not forget to write the init method on the form , The form data source properties is as follows
AllowCheck,AllowDelete,AllowCreate is set to "No",LinkType  "Passive",Insert at end  "No".

                                                                              Vivek Chirumamilla







Monday, 16 January 2012

Writing a display method in Ax 2009

Hi friend we are going  learn about the display method in Ax 2009 . We have a table say Table1. We have to display a field say Field value in Table1,which is coming from field2 from Table2.Say we have a common field called Cfield ,based on the value of Cfield the value of field we have to display field2 value in Table1.
Create a new method on Table1 write the code below,

// display method()
display Field2 field2()
{
    return this.Table2(this.Cfield).field2;
}
create a new method in Table1 and write the code below,

Table2 table2(Cfield cfield = this.cfield,
                                   boolean _forUpdate = false)
{
    return Table2::find(Cfield,_forUpdate);
}
Now drag drop the display method to the form of Table1
We we change the common field value the field value changes, Dont forget to change the properties of dragged form control.
                                                                Vivek Chirumamilla


Sunday, 15 January 2012

How to add a image to a form in Ax 2009

Hi friends ,

   Today we are going to add a image to form below the grid to diplay the related image,
In form take a new group and add a window control to display the image.Add a button group and take a menu item button from it. The properties of menu item are as follows,
Property                           Value
Name                            CompanyImage
MenuItemType              Display
MenuItemName            CompanyImage
Text Item                       image
DataSource                  InventTable
In class declaration of your form declare a container and add a method on form of to load the images,
the code for form is as follows,

void loadImage()
{
    Image        img;
    CompanyImage companyImage;
    ;
    companyImage = CompanyImage::find(
        InventTable.dataAreaId,
         InventTable .TableId,
         InventTable .RecId);
    if (companyImage.Image)
    {
        img = new Image();
        img.setData(companyImage.Image);
        ItemImage.image(img);
    }
    else
    {
        ItemImage.image(null);
    }
}
Take a button under menuitem buton and name it as "save as"
to save the image which u have created  take a new method on form and write the following code

void saveImage()
{
    Image    img;
    Filename name;
    str      type;
    #File
    ;
    if (!imageContainer)
    {
       return;
    }
    img = new Image();
    img.setData(imageContainer);
    type = '.'+strlwr(enum2value(img.saveType()));
    name = WinAPI::getSaveFileName(
        element.hWnd(),
        [WinAPI::fileType(type),#AllFilesName+type],
        '',
        '');
    if (name)
    {
        img.saveImage(name);
    }
}

And write a active method in datasource properties
  element.loadImage();
 And in save button override the clicked method and write the code as following
 element.saveImage();
By this a image is displayed by using this functionality
        By vivek chirumamilla

Monday, 9 January 2012

Create LookUp using X++ in Ax 2009

Hi Friends,

 Today we are going to create look up using code
1. Create a Form
2.Add a string Edit Control
3.In the methods of control write the following code

public void lookup()

{
//super();


// Declaration
Query   LookupQuery    =   new Query();

QueryBuildDataSource     LookupQueryBuildDataSource;

QueryBuildRange                  LookupQueryBuildRange;
SysTableLookup CustomSysTableLookup =       SysTableLookup::newParameters(tableNum(CustTable), this);

;

// Add fields that you want in Lookups

CustomSysTableLookup.addLookupField(fieldNum(CustTable, AccountNum));

CustomSysTableLookup.addLookupField(fieldNum(CustTable,Name));

LookupQueryBuildDataSource =

LookupQuery.addDataSource(tableNum(CustTable));

LookupQueryBuildRange=

LookupQueryBuildDataSource.addRange(fieldNum(CustTable,AccountNum));

//LookupQueryBuildRange.value(queryValue(NOYESCOMBO::Yes));

// Execute the Query

CustomSysTableLookup.parmQuery(LookupQuery);

CustomSysTableLookup.performFormLookup();

}
Vivek Chirumammila

Friday, 6 January 2012

How to open a form by using code

Hi friends ,

      Today we are going to open a form using code.. Its a simple way to do

 if(inventtable.Family == family::MettalicCore)
   {
   new MenuFunction(MenuItemDisplayStr(Attributes1),MenuItemType::Display).run();
    }
    else
    {
     new MenuFunction(MenuItemDisplayStr(Attributes),MenuItemType::Display).run();
     }
Here we are opening a form of Attributes1 and Attributes form its a simple way.Block Super()

Here is another way take a look


static void OpenFormByCodeB()
{ FormRun formRun;
Args args = new Args();
;
args.name(formstr(CustTable));
args.record(CustTable::find('ABC'));

formRun = ClassFactory.formRunClass(args);
formRun.init();
formRun.run();
formRun.wait();
}

Now if we tweak this a little bit, we can add our code
Like this:

static void OpenFormByCodeB()
{ Object formRun;
Args args = new Args();
;
args.name(formstr(CustTable));
args.record(CustTable::find('ABC'));

formRun = ClassFactory.formRunClass(args);
formRun.init();

formRun.yourmethodgoeshere(); /* !!

formRun.run();
formRun.wait();
}

By changing the type of formRun from class FormRun to class Object, we can implement and execute extra methods on our destination form! This gives us extra possibilities for customizations. You can pass along extra parameters for example.
Only drawback: While programming, your method doesn't show up in the IntelliSense, showing all the available methods. So be carefull of typo's. (They don't give a compile error, but they will give you a run-time error.)
 Thank you bye
                                                                                      Vivek Chirumamilla