La clase UnitOfWork apareció con la versión 2012 de Dynamics AX para facilitar la tarea de inserción o modificación de datos de forma masiva, ya que esta tarea se complicó con el cambio del patrón de modelado de datos, debido a las relaciones basadas en claves subrogadas.

Desde la versión 2012, Microsoft recomienda que las relaciones entre tablas se lleven a cabo por medio de las claves subrogadas para mejorar el rendimiento de la base de datos. Estas claves deben estar formadas por una variable entera de 64 autoincremental, justo el funcionamiento que tiene el campo estándar RecId.

Esta recomendación, no se hacía con versiones anteriores, puesto que para un usuario, sería difícil comprender los datos cuando realizase un lookup de una clave externa, para seleccionar datos de la tabla relacionada, lo que se solucionó introduciendo el concepto de clave de sustitución, de modo que, cuando el usuario vea el campo que hace la relación de las tablas, no verá realmente la clave primaria, si no, que aparecerá el campo que indiquemos dentro de la clave de sustitución, el cual tiene que ser una clave alternativa de campo único.

Debido a todo esto, la inserción masiva de datos se complica, ya que al ser el RecId el campo por el que se va a realizar la relación, no se sabrá su valor hasta que el campo esté realmente insertado, lo que obliga a ir insertando los registros de uno en uno, e ir consultando el valor del RecId una vez insertado para poder relacionar los registros.

Es por este motivo por el que aparece la clase UnitOfWork. Su funcionamiento es el siguiente:

  • Se relacionan los registros que queremos insertar utilizando las variables
  • Al insertar, el sistema se encarga de guardar los registros de forma ordenada, con sus relaciones, y va actualizando los RecId de los campos relacionados teniendo en cuenta la integridad de la transacción.

Imaginando el siguiente ejemplo en el que hay dos tablas relacionadas, una tabla padre y una tabla hija, que están relacionadas por el RecId de la tabla padre.

Relación de tablas por RecId

Esta sería la forma de insertar datos de la tabla padre e hija de forma masiva mediante la clase UnitOfWork, lo que lleva a una gran mejora de rendimiento.

// Variables de tipo buffer
AXZParentTable  parentTable;
AXZChildTable   childTable;

// Instancia de UnitOfWork (Obligatoriamente ejecutar en servidor)
UnitofWork      unitOfWork  = new UnitofWork();

parentTable.clear();
parentTable.initValue();
parentTable.ParentId    = “Padre”;
parentTable.Name        = “Name Padre”;
parentTable.Description = “Description padre”;
unitOfWork.insertonSaveChanges(parentTable);

childTable.clear();
childTable.initValue();
childTable.AXZParentTable(parentTable);
childTable.ChildId      = “Hijo”;
childTable.Name         = “Name Hijo”;
childTable.Description  = “Description Hijo”;
unitOfWork.insertonSaveChanges(childTable);

unitOfWork.saveChanges();

 

En distintos ejemplos que hemos llevado a cabo, hemos obtenido resultados en los que, realizando una inserción de unos 15.000 registros, al utilizar la clase UnitOfWork, el tiempo de ejecución se reduce prácticamente a la mitad en comparación con la inserción registro a registro.

Importante: La clase UnitOfWork solo puede utilizarse desde el servidor, por lo que no podemos ejecutar este código desde el cliente. Si necesitamos ejecutarlo desde un Job por ejemplo, que se ejecuta desde cliente, para realizar alguna prueba, deberemos desde este Job llamar a métodos de una clase que se ejecuten en servidor..

 

Si quieres saber más sobre esta nueva característica de AX, no dudes en visitar la plataforma e-learning de AXAZURE.com