Hi,
I’ve a problem. I have a template that starts by building a data structure by making different calls.
This take about 20 minutes to retrieve datas.
Then I have 4 foreach loops that process the data and displaying data in differents forms.
I think that every time there is a foreach, it will retrieve the data again, so for a single foreach it takes 20 minutes, for 2 foreach it takes 40 minutes and for 3 foreach 60 minutes.
How can I optimise the result rendering ? How can I write my code in order to get datas only one time and use it many times ? I can work only at Template level.
Based on limited evidence (treat as hypothesis), here is a cautious take: Summary
The long‑running delay is caused by rebuilding the same data collection inside each foreach block. Create the collection once, keep it in a variable (or cache it), and reuse that instance in all subsequent loops. The expensive operation will then run only a single time and the overall processing time is dramatically reduced.
Why it happens
foreach iterates over whatever enumerable you pass to it.
If the enumerable is produced by a method that performs a heavy query or transformation and that method is called inside each loop, the heavy work is repeated for every block.
What to do
Materialise the collection once
// Heavy operation – runs only once (≈20 min)
var records = BuildDataStructure(); // returns IList<T> or IEnumerable<T>
// First processing block
foreach (var r in records)
{
// …
}
// Second processing block
foreach (var r in records)
{
// …
}
// Additional blocks can reuse the same 'records' variable
If the source is a LINQ query, force a single enumeration
var records = (from x in source
where x.IsActive
select ExpensiveTransform(x))
.ToList(); // forces one pass and stores the results
Cache the collection for repeated document generation (optional)
Store the list in a static field, a singleton service, or an external cache (e.g., MemoryCache, Redis).
Subsequent requests retrieve the cached list instead of executing the heavy query again.
private static readonly Lazy<IReadOnlyList<MyRecord>> _cachedRecords =
new Lazy<IReadOnlyList<MyRecord>>(BuildDataStructure);
// Use
var records = _cachedRecords.Value;
When using Aspose.Words mail‑merge with a custom data source
Implement IFieldMergingCallback (or the appropriate callback) and keep the retrieved rows in a private collection.
The callback methods (FieldMerging, ImageFieldMerging) read from that cached collection instead of re‑executing the original query.
Verify the change
Add logging or a stopwatch around BuildDataStructure() to confirm it is invoked only once during the whole operation.
By materialising the data once and reusing the same in‑memory collection across all foreach sections, the heavy data‑retrieval code runs a single time and the cumulative delays disappear.
Please validate this behaviour with your exact SDK version and a minimal repro, as support can vary by release.
LINQ in .NET implements deferred execution, which means that all operations applied to a collection expession are performed only when the collection is enumerated and even the collection expression itself is evaluated at this stage too. LINQ Reporting Engine mimics this feature, hence whenever structDonneesBC is enumerated, a data retrieval operation takes place, which is expected.
I am afraid that without looking into application code, we can only guess how to optimize the calls. The first thing to try is declaring a variable like <<var [v = Query.GetDescendants(Entity, "CollectionSystem")]>> and then calculate structDonneesBC upon this variable rather than a direct Query.GetDescendants(Entity, "CollectionSystem") call.