[X++] TempDB refresh Data on FormDatasource
When using a TempDB as a FormDatasource and populating the data with a populateData
method returning a Common i struggled to change the data when the caller changes.
In Dynamics AX it's a normal behavior on journal forms that the lines / details form changes displays the data related to the header record. When both forms are open simultaneously and selecting an other record on the header form, the lines form will refresh and display the related data.
The Scenario
My scenario was the following:
Header form
WMSShipment
Record: WMSShipment
Details form
WMSShipmentBasis
Record: WMSOrderTrans
TempDB: MyTmpDB
First code
In Class
I had a method in a class that looks like this:
public static MyTmpDB populateData(WMSShipmentId _shipmentId)
{
InventDim inventDimSum;
InventDim inventDim;
WMSOrderTrans wmsOrderTransSum;
WMSOrderTrans wmsOrderTrans;
MyTmpDB myTmpDB;
// ...
while select sum(Qty), shipmentId, itemId, inventDimId from wmsOrderTransSum
join plfInventConContainerId, InventDimId from inventDimSum
group by wmsOrderTransSum.ItemId, wmsOrderTransSum.ShipmentId, inventDimSum.InventBatchId
where wmsOrderTransSum.ShipmentId == _shipmentId
&& inventDimSum.InventDimId == wmsOrderTransSum.InventDimId
&& inventDimSum.InventBatchId
{
select firstOnly qty, ItemId, shipmentId, inventDimId from wmsOrderTrans
join InventBatchId, inventDimId from inventDim
where wmsOrderTrans.itemId == wmsOrderTransSum.itemId
&& wmsOrderTrans.shipmentId == wmsOrderTransSum.shipmentId
&& inventDim.inventDimId == wmsOrderTrans.inventDimId
&& inventDim.InventBatchId == inventDimSum.InventBatchId;
myTmpDB.InventBatchId = inventDim.InventBatchId;
myTmpDB.ItemId = wmsOrderTrans.ItemId;
// ...
myTmpDB.insert();
}
return myTmpDB;
}
This method selects needed data, inserts it to the table MyTmpDB
and returns the instance with the data.
On Form
With the init method on the form the caller record is beeing stored:
public void init()
{
// ...
if (element.args() && element.args().dataset() == tableNum(WMSShipment) && element.args().record().isFormDataSource())
{
wmsShipmentCaller_ds = element.args().record().dataSource();
}
// ...
super();
}
On the executeQuery method of DataSource WMSOrderTrans
I populated the data to my tempDB FormDataSource:
public void executeQuery()
{
super();
if (wmsShipmentCaller_ds)
{
// Fill tmpDB:
MyTmpDB.linkPhysicalTableInstance(MyTmpDB::populateData(wmsShipmentCaller_ds.cursor().(fieldNum(WMSShipment, ShipmentId))));
}
}
Result
So if i open both forms and changed the shipment on the header, the data of WMSOrderTrans got refreshed but the data of my temp table remained the same.
The Problem
Calling linkPhysicalTableInstance a second time showed me an error that it's already linked.
New Code (Solution)
To make it work that way I first changed the method for populating the data to take the common as parameter, delete all records and insert the new ones:
public static void populateData2Buffer(WMSShipmentId _shipmentId, MyTmpDB _buffer)
{
InventDim inventDimSum;
InventDim inventDim;
WMSOrderTrans wmsOrderTransSum;
WMSOrderTrans wmsOrderTrans;
// only refresh data if shipment changed
if (_buffer.ShipmentId != _shipmentId)
{
delete_from _buffer;
while select sum(Qty), shipmentId, itemId, inventDimId from wmsOrderTransSum
join inventBatchId, InventDimId from inventDimSum
group by wmsOrderTransSum.ItemId, wmsOrderTransSum.ShipmentId, inventDimSum.inventBatchId
where wmsOrderTransSum.ShipmentId == _shipmentId
&& inventDimSum.InventDimId == wmsOrderTransSum.InventDimId
&& inventDimSum.inventBatchId != ''
{
select firstOnly qty, ItemId, shipmentId, inventDimId from wmsOrderTrans
join inventBatchId, inventDimId from inventDim
where wmsOrderTrans.itemId == wmsOrderTransSum.itemId
&& wmsOrderTrans.shipmentId == wmsOrderTransSum.shipmentId
&& inventDim.inventDimId == wmsOrderTrans.inventDimId
&& inventDim.inventBatchId == inventDimSum.inventBatchId;
_buffer.inventBatchId = inventDim.inventBatchId;
_buffer.ItemId = wmsOrderTrans.ItemId;
// ...
_buffer.insert();
}
}
}
On the form
I declared two variables:
For the last RecId to recognize the change
RefRecId lastShipmentRecId;
and for the buffer
MyTmpDB myTmp;
executeQuery:
public void executeQuery()
{
super();
if (wmsShipmentCaller_ds)
{
MyTmpDB::populateData2Buffer(wmsShipmentCaller_ds.cursor().(fieldNum(WMSShipment, ShipmentId)), myTmp);
MyTmpDB.linkPhysicalTableInstance(myTmp);
}
}
linkActive:
public void linkActive()
{
super();
MyTmpDB::populateData2Buffer(wmsShipmentCaller_ds.cursor().(fieldNum(WMSShipment, ShipmentId)), myTmp);
}
active:
public int active()
{
int ret;
ret = super();
// ...
MyTmpDB_ds.research();
return ret;
}
And now the tempDB gets refreshed too when changing the record on the caller form.