Early versions of AX had isolated data between companies using the dataAreaId field and allowed data to be accessed by developers using the crosscompany and changecompany statements. With newer versions of AX more data is being shared between companies, such as the global address book. This has called for a new level of data isolation... Microsofts answer: Partitions. Partitions are one level above companies. A partition can have multiple companies underneath it and each company can only belong to one partition.
The partition to log in to can be defined on the client config or the user settings. Once the AX client has been opened, the current partition cannot be changed. To change partitions the user must exit the client and then open the client with a different config file. There is also no crosspartition or changepartition statements in the ax code making it very difficult to query data from a different partition.
If only it were this easy...
If you are creating a new table that you need to share a table between all partitions then you can set the "SystemTable" property to Yes then set "SaveDataPerCompany" to No and "SaveDataPerPartition" to No. The data in the table will be the same for all partitions.
Cross partition selects
The example below shows how to select data from a different partition. Since it will get a table buffer for records in a different partition, the display methods for the table will also need to be run on the other partition. The code will run in CIL so you will need to do an incremental CIL compile before running.
// This method executes the query on the other partition and returns the data
static container queryPartition(container _c)
QueryRun qr = new QueryRun(new Query(_c));
ret += [buf2Con(qr.getNo(1))];
// This method can execute table display methods on other partitions
static container execDisplayMethod(container _c)
[methodName, packedBuffer] = _c;
buffer = con2Buf(packedBuffer);
dictTable = new dictTable(buffer.TableId);
return [dictTable.callObject(methodName, buffer)];
// This will run on the current partition and call the methods to retreive data from the other partition
static server void main(Args _args)
SysUserInfo userInfo = SysUserInfo::find();
UserId runAsUserId = userInfo.Id; // user needs to have access to other partition
PartitionKey partition = "ps"; // Partition to select data from
DataAreaId company = "psus"; // company in the partition to select data from
q = new Query();
qbds = q.addDataSource(tableNum(CustTable)); // Table to select data for
// qbds.addRange(... // Filter the data that will be returned
perm = new RunAsPermission(runAsUserId);
// execute the query on the other partition and get the data
c = runAs(runAsUserId, classnum(AA_CrossPartition), staticmethodstr(AA_CrossPartition, queryPartition), q.pack(), company, userInfo.Language, partition);
for(i=1; i<= conLen(c); i++)
custTable = con2Buf(conPeek(c, i));
// call the custTable.name() display method on the other partition
name = conPeek(runAs(runAsUserId, classnum(AA_CrossPartition), staticmethodstr(AA_CrossPartition, execDisplayMethod), ["name", conPeek(c, i)], company, userInfo.Language, partition), 1);
// Display data from table buffer.
info(strFmt("%1 %2 %3", custTable.AccountNum, name, custTable.PaymTermId));
This code is just a simple example but can be adapted to have more functionality.
If you found this helpful or have any questions then please leave a comment.