Using report assemblies

In .NET Core and .NET 5 and above, the Roslyn compilation is used. The assemblies are loaded into memory only. It's possible to unload the report from memory using `report.Dispose()` method in builds starting from 2023.4.1. The rest article is about the .NET Framework. 

By default, all reports before rendering should be compiled in an assembly. In the .NET framework application if the assembly is loaded in memory then it is locked in any case until the application domain is unloaded.
In this case, the assembly is saved in the Windows temp directory and then is loaded in memory. Anyway loading of the report assembly as any other .NET assembly is a locked assembly file on the drive either in one or in another place and there is allocated memory.

There are several ways to avoid this problem:

  1. Use reports in your application as C# classes (you can save them as classes from the report designer). In this case, the report is being compiled with your application, and accordingly, it doesn't need to be compiled and loaded from the assembly.

    The disadvantage of this way is that your project should be recompiled with the new report class if you need to change the report template.

  2. Save reports as compiled assemblies in the Designer.

    The disadvantage of this way is that it is not useful to manage reports during the upgrade.

  3. Do not use report compilation. Instead of it, you could use the interpretation of the expressions in the report. You could enable this mode in the Calculation Mode report property.

    The disadvantage of this way is that not all expressions of the C# and VB.NET languages are interpreted. It's impossible to use events of components.

  4. Compilation and rendering a report in another application domain. In this case, after rendering a report it is possible to load it into the assembly with this application domain. The locked file could be removed afterward.
    The CreateReportInNewAppDomain() method of the StiReport class could be used to create a report and the UnloadReportAppDomain() method for uploading this report.

    The disadvantage of this way is that the RegData and RegBusinessObject methods are executed very slowly since the data marshaling to other domains is used. It is better to request data in the report. Creating and uploading the application domain needs time.

  5. In our opinion, the most efficient way is the compilation of a report when calling it the first time. On every next call, the report is loaded from the compiled assembly. In this case, only one copy of the report is stored in memory and there is only one assembly on the drive. The directory with the compiled report can be removed before using reports because they will be created again on the first request. You can find a sample code below showing how this way works. A new report assembly is created, if it does not exist, if the report was changed, if the .NET Framework for what the assembly was compiled and the version under which the application is run differ. If the second parameter of the GetReportFromAssembly() method is set to true, the report assembly will be loaded once even if you call the method several times.

    The disadvantage of this way is that the first run is slow.

    StiReport report = new StiReport();
    string folder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
    folder = Path.Combine(folder, "Stimulsoft\\CompiledReports");
    folder = Path.Combine(folder, System.Runtime.InteropServices.RuntimeEnvironment.GetSystemVersion().ToString());
    string compiledReportFile = Path.Combine(folder, report.GetReportAssemblyCacheName());
    if (File.Exists(compiledReportFile))
    	report = StiReport.GetReportFromAssembly(compiledReportFile, true);
    	if (!Directory.Exists(folder)) Directory.CreateDirectory(folder);
  6. Precompilation of reports when updating them. This method is a modification of the previous one. After updating reports in the application or if they are not present, or, if necessary, the process of compiling all reports starts, which are used in the application. Before compilation, the old version of assemblies is removed.

    The disadvantage of this way is that the compilation of reports could take some time.


Please sign in to leave a comment.