Microsoft Dynamics AX 2012, tablas TempDB y Formularios

En versiones anteriores disponíamos de diferentes técnicas (no muy intuitivas) para utilizar tablas temporales en formularios. Estas mismas técnicas pueden utilizarse en AX 2012, donde además, tenemos diferentes tipos de estas tablas. En particular me interesan las tablas de tipo TempDB porque son las que mejor rendimiento obtienen, al estar gestionadas por el motor de Microsoft SQL Server. Este es uno de esos post que escribo para tener localizada la información y volver a ella en futuras referencias 🙂

Una versión muy sencilla de uso de estas tablas es similar a como lo hacíamos en la versión 2009, sustituyendo la función setTmpData por linkPhysicalTableInstance. De esta forma, creamos un formulario, añadimos la tabla temporal al origen de datos, etc. y finalmente el método init del formulario queda de esta forma:

public void init()
{
    // ...
   
    super();

    JAEETablaTmp.linkPhysicalTableInstance(JAEETablaTmp::createRecords(desde, hasta));
}

El origen de datos se enlaza con un buffer de la tabla temporal devuelto por la función que inserta los datos. De forma que esos datos que devuelve la función son los que se muestran en el formulario.

Una forma más avanzada de hacerlo, que ofrece más flexibilidad para actualizar los datos posteriormente, es usar una variable de la tabla temporal,que posteriormente podamos manipular. En este caso hay que tener en cuenta el ámbito (scope) de existencia de los datos en la tabla temporal, para lo cual debemos pasar la misma variable a las funciones que manipulen los datos, para no perderlos.

public class FormRun extends ObjectRun
{
    JAEETablaTmp   tmpTable;
}

public void init()
{
    // ...

    super();

    // Hay que pasar el buffer a la función para mantener el ámbito
    JAEETablaTmp::createRecords(tmpTable, desde, hasta);

    // ...

    // Enlazar el buffer con la tabla temporal
    JAEETablaTmp.linkPhysicalTableInstance(tmpTable);
}

Así podremos actualizar los datos posteriormente, en mi caso con la llamada a un botón en el formulario que obtiene parámetros de otros controles, de esta forma:

void clicked()
{
    JAEETablaTmp::createRecords(tmpTable, FromDate.dateValue(), ToDate.dateValue());
    JAEETablaTmp_ds.executeQuery();
}

Destacar cómo la variable temporal declarada en el formulario se pasa a la función que genera los datos para mantener siempre la referencia a la misma variable que está enlazada al origen de datos. La función gestiona los datos en esta misma variable, y la devuelve, de esta manera:

public static client JAEETablaTmp createRecords(
    JAEETablaTmp    _tmpBuffer,
    FromDate        _desde,
    ToDate          _hasta)
{
    // ...

    delete_from _tmpBuffer;

    while select DatePhysical, ItemId, sum(Qty)
        // ...
    {
        _tmpBuffer.clear();
        // ...
        _tmpBuffer.insert();
    }

    return _tmpBuffer;
}

Una particularidad que hay que tener en cuenta es que, en el momento de enlazar la tabla temporal con el origen de datos, la variable buffer no puede estar vacía, o el enlace no se realiza. Ésto no es ningún problema en el primer ejemplo, ya que simplemente no se mostrará ningún dato en el formulario; pero si utilizamos la segunda técnica y el enlace con la variable no se realiza correctamente,  posteriores actualizaciones de la variable no se verán reflejadas en el origen de datos, y tampoco se mostrará ningún error.

Una forma sencilla de evitar esto es insertar un registro vacío en la tabla antes de realizar el enlace con el origen de datos:

public void init()
{
    // ...

    super();

    // Hay que pasar el buffer a la función para mantener el ámbito
    JAEETablaTmp::createRecords(tmpTable, desde, hasta);

    // Si la tabla no tiene registros, la tabla no se enlaza!!
    if (!tmpTable)
        tmpTable.insert(); // IMPORTANTE!

    // Enlazar el buffer con la tabla temporal
    JAEETablaTmp.linkPhysicalTableInstance(tmpTable);
}

Espero que os sirva 😀