水晶报表 - 关闭数据库连接

6
这是关于C#、Visual Studio 2008和随VS2008一起提供的Crystal Reports的内容。
我有一个Crystal Report Viewer表单,它驻留在一个DLL中。该DLL负责加载基于报告文件名的水晶报告,并在表单上显示报告。
当我完成水晶报告后,会对已加载的reportdocument对象调用dispose。但是,数据库连接仍然存在。
Crystal似乎检测到与同一数据库的主应用程序的其他连接,并保持其连接处于打开状态。当关闭主应用程序的数据库连接时,水晶连接才会关闭。
有没有办法强制Crystal关闭其连接,而不关闭主应用程序的数据库连接?
6个回答

1

马克的代码似乎在某种程度上缓解了情况,尽管有点倒退,应该是这样的:

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();

这并没有完全解决漏洞,但确实有所帮助。


1

我遇到了同样的问题,只不过我使用的是Sybase。不久前,当我发布我编写的处理连接释放的代码时(但那并没有起作用),我看到了一个错误!我修复了这个错误,并且现在它似乎可以工作了。我已经打开了近100份报告,而以前我只能打开10份。如果你尝试这个方法,请让我知道它是否适用于你。

在关闭包含Crystal Reports查看器的窗口之前,我正在执行以下操作:

var rd = (ReportDocument)crystalReportViewer1.ReportSource;
foreach (Table table in rd.Database.Tables)
   table.Dispose();
rd.Database.Dispose();
rd.Close();
rd.Dispose();
GC.Collect();

马克


1

你是如何连接数据库的?是通过在运行时创建自己的连接并设置身份验证,还是让Crystal报告中存储的连接进行连接?如果以任何方式自己进行连接,则必须在处理报告之前手动关闭连接并调用dispose。

这很可能是内存泄漏。我以前也遇到过这种情况。Crystal Reports也存在内存泄漏问题,在他们的论坛上经常被讨论,但在我几年前使用它时没有发布修复程序。我放弃了Crystal并选择了其他选项。


0

我对Crystal Reports不是太熟悉,但有许多对象由于继承链包括IDisposable接口而具有无用的Dispose()方法。如果服务器上没有遇到任何性能问题,那就不必担心它。垃圾回收器准备好时,GC会处理客户端连接。你不应该试图比GC更聪明,否则只会给自己带来更多的麻烦。

并且,请始终在可用时调用Dispose()(或者使用using{})。


这实际上是关于数据库连接的问题。主要应用程序具有恢复和备份数据库的功能。Crystal数据库连接会阻止此操作。我在谷歌上搜索了一下,发现释放报表可以关闭连接,但仅当Crystal是唯一连接时才能这样做。 - user87945
我假设你正在使用MSSQL,是吗?为什么不使用内置的备份/还原功能呢? - Ariel
因为该产品旨在供非技术人员使用。拥有两个菜单项,分别为备份/还原,比进入SQL管理工具,以用户身份登录并具有这些权限等更容易理解。 - user87945
在使用“总是”这个词时,我会小心谨慎。你开始说许多对象有一个无用的Dispose方法,那么总是使用它或者使用它们是否有意义呢? - Chris Nicola

0
你可以在CRConfig.xml中更改超时选项,这样连接将会自动关闭。

0
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();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接