问题
This is in C#, Visual Studio 2008, crystal reports that came with VS2008
I've got a crystal report viewer form that resides in a DLL. The DLL is responsible for loading the crystal report (based on report filename), and displaying the report on the form.
When I'm done with the crystal report, i call dispose on the loaded reportdocument object. However, the database connection remains.
Crystal seems to detect that there are other connections (from my main application) to the same database, and keeps its connection open. The crystal connection is closed when the main applications database connection is closed.
Is there any way to force crystal to close its connection, with out closing the main applications database connection?
回答1:
How are you connecting to the database, by creating your own connection at runtime via setting the authentication or are you letting Crystal do the connection via the stored connection in the report? If you are doing your own connection in any way, shape, or form, you have to manually close the connection and call the dispose before disposing the report.
It is quite possible this is a memory leak. I have experienced these before. There is also a memory leak issue with Crystal Reports and is talked about on their forum quite a bit but no fix was issued when I was using it a few years ago. I ditched Crystal for other options.
回答2:
I'm not too familiar with Crystal Reports, but there are many objects which have a useless Dispose() method due to an inheritance chain that includes the IDisposable interface. If you are not seeing any performance problems on the server, then don't worry about it. The GC will take care of the connections on the clients when it is ready. You shouldn't try to be smarter than the GC, you will only give yourself more headaches.
And, always call Dispose() (or using{}) when it is available.
回答3:
I had the same problem, except I'm using Sybase. A little while ago I was posting the code I wrote to dispose of the connection (and that didn't work) when I saw an error! I fixed the error, and, cross my fingers, now it seems to work. I've opened almost 100 reports where I couldn't open 10 before. If you try this, please let me know if it works for you.
Here is what I'm doing right before I close the window that contains the Crystal Reports viewer:
var rd = (ReportDocument)crystalReportViewer1.ReportSource;
foreach (Table table in rd.Database.Tables)
table.Dispose();
rd.Database.Dispose();
rd.Close();
rd.Dispose();
GC.Collect();
Mark
回答4:
Marks code seems to somewhat relieve the situation although it is a bit backwards, should be something like:
ReportDocument rd = (ReportDocument) viewer.ReportSource;
foreach (Table table in rd.Database.Tables)
table.Dispose();
viewer.ReportSource = null;
rd.Database.Dispose();
rd.Close();
rd.Dispose();
rd = (ReportDocument) viewer.ReportSource;
GC.Collect();
This didn't completely plug the leak for me but certainly helped.
回答5:
connectDB();
ReportDocument cryRpt = new ReportDocument();
DataSet ds;
cmd = new SqlCommand("Select * from LeaveJO where IDno = '" + textBox1.Text + "'", conn);
da = new SqlDataAdapter(cmd);
ds = new DataSet();
da.Fill(ds, "LeaveJO");
cryRpt.Load(@"JOleave.rpt");
cryRpt.SetDataSource(ds);
TableLogOnInfos crtableLogoninfos = new TableLogOnInfos();
TableLogOnInfo crtableLogoninfo = new TableLogOnInfo();
ConnectionInfo crConnectionInfo = new ConnectionInfo();
Tables CrTables;
crConnectionInfo.ServerName = cs.serverName;
crConnectionInfo.DatabaseName = cs.dbName;
crConnectionInfo.UserID = cs.userID;
crConnectionInfo.Password = cs.password;
CrTables = cryRpt.Database.Tables;
foreach (CrystalDecisions.CrystalReports.Engine.Table CrTable in CrTables)
{
crtableLogoninfo = CrTable.LogOnInfo;
crtableLogoninfo.ConnectionInfo = crConnectionInfo;
CrTable.ApplyLogOnInfo(crtableLogoninfo);
}
cryRpt.Refresh();
// cryRpt.PrintToPrinter(2, true, 1, 2);
crystalReportViewer1.ReportSource = cryRpt;
crystalReportViewer1.Visible = true;
cryRpt.Dispose();
conn.Dispose();
来源:https://stackoverflow.com/questions/724323/crystal-reports-close-the-database-connection