2

I've written a small C# application to save reports to pdf using Crystal Reports. The problem I'm having is that as I save more reports, my application's handles continually increase, and I can see new database connections being made and left open after each report is saved. Eventually the application gets an exception from Crystal saying 'database logon error', or I get a C++ runtime error complaining about 'R6025: pure virtual function call'.

I'm looking at application handles using process explorer, as per this technique. I'm checking database connections using MS SQL Server's activity monitor. Each saved report causes about another 100 open handles to 'Semaphores' and 'Events' and 2 database connections.

I believe I'm disposing of the report properly by calling Close() then Dispose(), as mentioned here. Other suggestions around the web include manually closing database connections (Crystal reports - close the database connection) and calling GC.Collect(), however none have worked in my case.

Some environment details

  • Visual Studio 2012
  • C# Console application targeting .NET 4.5.1 runtime
  • Database: MSSQL Server 2012
  • Crystal Reports for .NET Framework 4.0, version 13.09.1312
  • A Crystal Report document using the SAP database connection (this is important - see answer)

Here's a sample application that exhibits the same problem:

using System;
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared;

namespace ExampleConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                SaveReport();
            }
        }

        static void SaveReport()
        {
            Console.WriteLine("loading report...");

            ReportDocument rpt = new ReportDocument();
            rpt.Load("test.rpt");

            rpt.SetDatabaseLogon("username", "password");
            foreach (IConnectionInfo info in rpt.DataSourceConnections)
            {
                info.IntegratedSecurity = false;
                info.SetConnection("SQL", "our_database", "username", "password");
            }
            rpt.ExportToDisk(ExportFormatType.PortableDocFormat, "test.pdf");

            WaitForKeypress("about to dispose report");

            // attempt to manually close tables / database links
            // none of the following commented code has had any effect

            // foreach (TableLink tl in rpt.Database.Links)
            // {
            //     tl.Dispose();
            // }
            // rpt.Database.Links.Reset();
            // rpt.Database.Links.Dispose();

            // foreach (Table table in rpt.Database.Tables)
            // {
            //     table.Dispose();
            // }
            // rpt.Database.Tables.Reset();
            // rpt.Database.Tables.Dispose();
            // rpt.DataSourceConnections.Clear();
            // rpt.Database.Dispose();

            rpt.Close();
            rpt.Dispose();

            // rpt = null;
            // GC.Collect();

            WaitForKeypress("disposed");
        }

        private static void WaitForKeypress(string msg = "press a key...")
        {
            Console.WriteLine(msg);
            Console.ReadLine();
        }
    }
}

Can someone tell me what I'm doing wrong?

Community
  • 1
  • 1
uozuAho
  • 381
  • 1
  • 11

1 Answers1

1

Are you using the crystal report for SAP B1? If so, this is an issue with running the code on Windows Server and using the SAP B1 Database Connection type in your Crystal report. I had the same problem using the Boyum Usability Pack in SAP B1 on Windows Server 2012. After changing the connection type in the Crystal report to OLE(ADO) it worked. I think the SAP B1 Database Connection type is buggy, or possibly not meant to be used for this purpose.

See this video on youtube which explains how to set the driver to OLE(ADO). http://youtu.be/j7kpj2tR3d4

Asagohan
  • 583
  • 5
  • 19