In the e-conomic API, using data classes is a powerful way of optimizing the retrieval, creation or updating of multiple entity properties – or even multiple entities – to use as few round-trips as possible.

However, many developers are put off by the fact that when using data classes, only simple-type properties are returned – thus still requiring round-trips to retrieve properties of referenced objects.

Suppose, for example, that we wish to list the product number, product name and product group number of all our products. The following would seem to be the obvious way of achieving this:

IProduct[] arrP = session.Product.GetAll();
IProductData[] arrPD = session.ProductData.GetDataArray(arrP);

foreach (IProductData pd in arrPD)
{
Console.WriteLine("Number: " + pd.Number.ToString());
Console.WriteLine("Name: " + pd.Name);
Console.WriteLine("Group: " + pd.ProductGroup.Number.ToString());
Console.WriteLine("");
}

This should result in only two round-trips – one for Product.GetAll() and one for ProductData.GetDataArray() – right? Wrong! For each product group, the above code will also generate a round-trip to retrieve the product group number (effectively a call to the SOAP function ProductGroup_GetNumber). The final result is a number of round-trips equalling n+2, with n denoting the number of products. This seems very unnecessary – especially since the number of products is usually several orders of magnitude higher than the number of product groups.

First of all – why are the data classes designed this way? Why does the IProductData class return IProductGroup object references instead of IProductGroupData objects? While that would seem to be more consistent with the point of data classes, consider the ramifications if all data objects were to include referred objects as other data objects. In the above example:

IProductData would include IProductGroupData
• which would include IAccountData
• which might include IVatAccountData (IAccount.VatAccount is NULLable)
• which would include IAccountData
• etc.

In other words, this could quickly result in massively ‘recursive’ retrievals of data one would in most cases not have any use for.

Luckily, there is another way of reducing the number of round-trips to an absolute minimum: Retrieve all product groups in one go, and store them in a dictionary with IProductGroup as key:

IProductGroup[] arrPG = session.ProductGroup.GetAll();
IProductGroupData[] arrPGD = session.ProductGroupData.GetDataArray(arrPG);

Dictionary<IProductGroup, IProductGroupData> pgd = new Dictionary<IProductGroup, IProductGroupData>();

for (int x = 0; x < arrPG.Length; x++)
{
pgd[arrPG[x]] = arrPGD[x];
}

IProduct[] arrP = session.Product.GetAll();
IProductData[] arrPD = session.ProductData.GetDataArray(arrP);

foreach (IProductData pd in arrPD)
{
Console.WriteLine("Number: " + pd.Number.ToString());
Console.WriteLine("Name: " + pd.Name);
Console.WriteLine("Group: " + pgd[pd.ProductGroup].Number.ToString());
Console.WriteLine("");
}

This generates only four round-trips: ProductGroup.GetAll(), ProductGroupData.GetDataArray(), Product.GetAll() and ProductData.GetDataArray() – irrespective of the number of products or product groups. A similar trick can be used with any data class that includes object references.

A final, and somewhat related performance tip: Throwing the result of GetAll() at GetDataArray() may of course still lead to massive amounts of data being downloaded. As a general rule, we recommend that you split the GetAll() result into batches of 500 entities for the subsequent data retrieval. While this will of course result in slightly more round-trips, it is much less prone to timeouts in either end.

Take a look at our API documentation.