Select crosspartition in AX2012

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...

partition3.png

Global tables

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.

partition1.png

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.

class AA_CrossPartition

{

}

// This method executes the query on the other partition and returns the data

static container queryPartition(container _c)

{

container ret;

QueryRun qr = new QueryRun(new Query(_c));

while (qr.next()){

ret += [buf2Con(qr.getNo(1))];

}

return ret;

}

// This method can execute table display methods on other partitions

static container execDisplayMethod(container _c)

{

container packedBuffer;

common buffer;

str methodName;

DictTable dictTable;

[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)

{

RunAsPermission perm;

SysUserInfo userInfo = SysUserInfo::find();

UserId runAsUserId = userInfo.Id; // user needs to have access to other partition

container c;

Query q;

QueryBuildDataSource qbds;

CustTable custTable;

int i;

PartitionKey partition = "ps"; // Partition to select data from

DataAreaId company = "psus"; // company in the partition to select data from

CustName name;

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);

perm.assert();

// 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));

}

CodeAccessPermission::revertAssert();

}

partition2.png

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.

#ax2012 #partition #runAs

RECENT POSTS:

© 2015 by Stephen Mann

  • LinkedIn Black Round
  • Facebook Black Round
  • emailicon.png