Caching display methods on a form datasource

When display (and edit) methods from a table is used on a form they can easily be cached using the cacheAddMethod on the form datasource in its init-method like this:

    this.cacheAddMethod(tableMethodStr(CustTable, Name));

But what about display methods created on the datasource? They can be cached by adding a few lines of code and by that improving performance significantly.

In this example we have a form listing customers and an amount summary of all there transactions.

The display method for the amount summary could look something like this:

display AmountMST calcAmount(CustTable _custTable)
{
    CustTrans   custTrans;

    select firstOnly sum(AmountMST) from custTrans
        where custTrans.AccountNum == _custTable.AccountNum;

    return custTrans.AmountMST;
}

Doing it like this would decrease performance due to the constant reading of data each time a customer record is being read and the field is updated. So to minimize the load we need to cache the information and cut down the number of SQL server round trips.

In the classdeclaration on the form create a variable of the type Map. In this example we will be caching an amount calculation based on the customer table:

public class FormRun extends ObjectRun
{
    Map amountCache;
}

Then we change our display method to utilize the amountCache map. In this example I have moved the select part to a seperate method. This is not necessary but if you really want to tweak you could argue that the declaration of the CustTrans costs memory allocation unnecessarily when looking data up in the cache and not calculating it. But in the big picture it probably wont cost noticeably performance. Anyways, here is the new display method:

display Amount amountSum(CustTable _custTable)
{
   // Init cache if not already done
    if (! amountCache)
    {
        amountCache = new Map(Types::Int64, Types::Real);
    }

    // Check for value in cache. If not set do so
    if (! amountCache.exists(_custTable.RecId))
    {
        amountCache.insert(_custTable.RecId, this.calcAmount(_custTable.AccountNum));
    }

    // Lookup value in cache and return it
    return = amountCache.lookup(_custTable.RecId);
}