Skip to main content

Notifications

Announcements

No record found.

Dynamics 365 Community / Forums / Finance forum / How to improve perform...
Finance forum
Unanswered

How to improve performance in creating SSRS reports with X++ ?

Posted on by 37

Hello community,

I’m working on an integration where I create free text invoices from data pulled from a third-party source. After generating and posting the invoices, I generate a custom SSRS report (as a PDF) and attach it to each free text invoice. However, this final step is taking a significant amount of time, especially as I’m processing a large volume of invoices.

Could anyone suggest improvements to my code or offer alternative methods to speed up this part of the process? Below is the code I’m using to generate the PDF and attach it to the invoice.

Thank you in advance for your help!

 
    public void generateAndAttachPDF(NPLOracleSupportHeader headerRecord)
    {
        CustInvoiceJour custInvoiceJour;
        CustInvoiceTable custInvoiceTable;
        PrintMgmtReportFormatName printMgmtReportFormatName;
        FreeTextInvoiceContract freeTextInvoiceContract = new FreeTextInvoiceContract();
        SrsReportRunController srsReportRunController;
        SRSPrintDestinationSettings printerSettings;
        System.Byte[] reportBytes;
        SrsReportRunService srsReportRunService;
        SRSProxy srsProxy;
        Microsoft.Dynamics.AX.Framework.Reporting.Shared.ReportingService.ParameterValue[] parameterValueArray;
        Map reportParametersMap;
        str fileName = "";
        SRSReportExecutionInfo executionInfo = new SRSReportExecutionInfo();

        // Fetch the invoice journal and table records
        select firstonly custInvoiceJour
            where custInvoiceJour.InvoiceId == headerRecord.NPLOracleInvoiceIdDynamics
            && custInvoiceJour.NPLInvoiceId == headerRecord.NPLOracleInvoiceId;

        if (!custInvoiceJour)
        {
            error("Invoice not found.");
            return;
        }

        select firstonly custInvoiceTable
            where custInvoiceTable.InvoiceId == custInvoiceJour.InvoiceId;

        if (!custInvoiceTable)
        {
            error("Invoice table record not found.");
            return;
        }

        // Set up the file name and print management report format
        fileName = custInvoiceJour.InvoiceId + ".pdf";
        printMgmtReportFormatName = ssrsReportStr(CustomFormatReport, Report);

        // Initialize the report contract with the invoice record ID
        freeTextInvoiceContract.parmCustInvoiceJourRecId(custInvoiceJour.RecId);

        // Initialize the report controller once
        srsReportRunController = new SrsReportRunController();
        srsReportRunController.parmReportName(printMgmtReportFormatName);
        srsReportRunController.parmExecutionMode(SysOperationExecutionMode::Asynchronous);
        srsReportRunController.parmShowDialog(false);
        srsReportRunController.parmLoadFromSysLastValue(false);
        srsReportRunController.parmReportContract().parmRdpContract(freeTextInvoiceContract);

        // Configure print settings to generate the PDF
        printerSettings = srsReportRunController.parmReportContract().parmPrintSettings();
        printerSettings.printMediumType(SRSPrintMediumType::File);
        printerSettings.fileFormat(SRSReportFileFormat::PDF);
        printerSettings.fileName(fileName);
        printerSettings.overwriteFile(true);

        try
        {
            // render the report
            srsReportRunService = new SRSReportRunService();
            srsReportRunController.parmReportContract().parmReportServerConfig(SRSConfiguration::getDefaultServerConfiguration());
            srsReportRunController.parmReportContract().parmReportExecutionInfo(executionInfo);
            srsReportRunService.getReportDataContract(srsReportRunController.parmReportContract().parmReportName());
            srsReportRunService.preRunReport(srsReportRunController.parmReportContract());
            srsReportRunService.parmIsInBatch(true);
            
            reportParametersMap = srsReportRunService.createParamMapFromContract(srsReportRunController.parmReportContract());
            parameterValueArray = SrsReportRunUtil::getParameterValueArray(reportParametersMap);

            srsProxy = SRSProxy::constructWithConfiguration(srsReportRunController.parmReportContract().parmReportServerConfig());

            // render report to byte array
            reportBytes = srsProxy.renderReportToByteArray(
                srsReportRunController.parmReportContract().parmReportPath(),
                parameterValueArray,
                printerSettings.fileFormat(),
                printerSettings.deviceInfo()
            );

            // Attach the generated PDF to the invoice
            if (reportBytes)
            {
                this.attachPDFToInvoice(custInvoiceTable, reportBytes, fileName);
            }
            else
            {
                error("Failed to render the report to a byte array.");
            }
        }
        catch (Exception::Error)
        {
            error("An error occurred during the report generation.");
        }
    }

    public void attachPDFToInvoice(CustInvoiceTable custInvoiceTable, System.Byte[] reportBytes, str fileName)
    {
        System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(reportBytes);
        DocuRef docuRef;

        // Attach the PDF in a transaction
        ttsBegin;
        docuRef = DocumentManagement::attachFile(
            custInvoiceTable.TableId,
            custInvoiceTable.RecId,
            custInvoiceTable.DataAreaId,
            DocuType::typeFile(),
            memoryStream,
            fileName,
            System.Web.MimeMapping::GetMimeMapping(fileName),
            custInvoiceTable.InvoiceId
        );
        ttsCommit;
    }
 
 
  • How to improve performance in creating SSRS reports with X++ ?

    ok I’ll look into those suggestions and update this thread with the results of the analysis, thanks again Martin.

  • Martin Dráb Profile Picture
    Martin Dráb 228,764 Most Valuable Professional on at
    How to improve performance in creating SSRS reports with X++ ?
    One option is starting by measuring the whole process to see which component is the most problematic. If the theory proves true and the data provider class (FreeTextInvoiceDP) takes a lot of time, look at details there. For example, you may find a particular slow query.
     
    Because slow queries are a common problem, you may actually start with them. You can look at something like Query store to check if there isn't anything obviously wrong. The Trace parser can highlight slow queries too.
     
    But of course, the problem may be caused by something else. We can't know without checking.
  • How to improve performance in creating SSRS reports with X++ ?

    Hello Martin,

    I’ve extended the data provider class for the free text invoice (FreeTextInvoiceDP), where I added some custom logic and populated the FreeTextInvoiceHeaderFooterTmp and FreeTextInvoiceTmp tables. Is this what you meant by the data preparation part? other than that I’ve just created a custom SSRS report using those two tables as the data source.

    Where do you suggest I start debugging to measure the processing time?

    Thanks so much for your help!

  • Martin Dráb Profile Picture
    Martin Dráb 228,764 Most Valuable Professional on at
    How to improve performance in creating SSRS reports with X++ ?
    You'll need a better idea about the problem before you can fix it.
     
    Looking at a small part of the solution and trying to guess performance problems isn't a good approach. Instead, measure what takes the most time. The slowest part of report printing usually is the data preparation, which may (but doesn't have to) be your case too. Note that such code isn't shown above.
     
     

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Anton Venter – Community Spotlight

Kudos to our October Community Star of the month!

Announcing Our 2024 Season 2 Super Users!

A new season of Super Users has arrived, and we are so grateful for the daily…

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 290,572 Super User 2024 Season 2

#2
Martin Dráb Profile Picture

Martin Dráb 228,764 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,148

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans