Select crosspartition in AX2012

May 3, 2015

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

 

 

 

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.

 

 

 

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

}

 

 

 

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.

 

 

 

Please reload

RECENT POSTS:
Please reload

© 2015 by Stephen Mann

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