【问题标题】:Crystal report database connections not disposingCrystal 报表数据库连接未处理
【发布时间】:2020-05-15 18:00:11
【问题描述】:

我在我的 asp.net Web 应用程序中使用 Visual Studio 2013 并大量使用 Crystal Reports。我的数据库是 SQL Server(使用 AWS RDS)。一切正常。唯一的问题是,从数据库方面来看,Crystal Report 连接即使在关闭浏览器窗口后也没有关闭/处理。它不断增加连接数。

这是我的代码:

ReportDocument cryRpt = new ReportDocument();

ParameterFields paramFields = new ParameterFields();
ParameterField paramField = new ParameterField();

cryRpt.Load(Server.MapPath("~/Reports/Report001.rpt"));

String host = System.Configuration.ConfigurationManager.AppSettings["SqlServer"];
String database = System.Configuration.ConfigurationManager.AppSettings["SqlDatabase"];
String user = System.Configuration.ConfigurationManager.AppSettings["SqlUsername"];
String password = System.Configuration.ConfigurationManager.AppSettings["SqlPassword"];

var connectionInfo = new ConnectionInfo
        {
            Type = ConnectionInfoType.SQL,
            ServerName = host,
            DatabaseName = database
        };

connectionInfo.IntegratedSecurity = false;
connectionInfo.UserID = user;
connectionInfo.Password = password;

TableLogOnInfo newLogonInfo = null;

foreach (CrystalDecisions.CrystalReports.Engine.Table currentTable in cryRpt.Database.Tables)
{
    newLogonInfo = currentTable.LogOnInfo;
    newLogonInfo.ConnectionInfo = connectionInfo;
    currentTable.ApplyLogOnInfo(newLogonInfo);
}

ParameterField pReportName = new ParameterField();
pReportName.ParameterFieldName = "REPONAME";
ParameterDiscreteValue dcpReportName = new ParameterDiscreteValue();

dcpReportName.Value = "REPORT";

pReportName.CurrentValues.Add(dcpReportName);
paramFields.Add(pReportName);

CrystalReportViewer1.ParameterFieldInfo = paramFields;
CrystalReportViewer1.Zoom(100);
CrystalReportViewer1.PrintMode = CrystalDecisions.Web.PrintMode.ActiveX;
CrystalReportViewer1.ReportSource = cryRpt;
CrystalReportViewer1.ReuseParameterValuesOnRefresh = true;
CrystalReportViewer1.ShowFirstPage();

// Disposing the report
foreach (CrystalDecisions.CrystalReports.Engine.Table currentTable in cryRpt.Database.Tables)
{
     currentTable.Dispose();
}

CrystalReportViewer1.ReportSource = null;
cryRpt.Database.Dispose();
cryRpt.Close();
cryRpt.Dispose();
cryRpt = (ReportDocument)CrystalReportViewer1.ReportSource;
CrystalReportViewer1.Dispose();

connectionInfo.Attributes.Collection.Clear();

GC.Collect();

尝试使用卸载方法也是这样。但没有运气。

    protected void CrystalReportViewer1_Unload(object sender, EventArgs e)
    {
       cryRpt.Close();
       cryRpt.Dispose();
       CrystalReportViewer1.Dispose();           
    }

作为一个临时解决方案,我使用存储过程从数据库手动终止睡眠数据库连接。

我正在使用 ODBC 连接来获取数据。 ODBC 凭据存储在配置文件中,并按如下方式检索。

String host = System.Configuration.ConfigurationManager.AppSettings["SqlServer"];
String database = System.Configuration.ConfigurationManager.AppSettings["SqlDatabase"];
String user = System.Configuration.ConfigurationManager.AppSettings["SqlUsername"];
String password = System.Configuration.ConfigurationManager.AppSettings["SqlPassword"];

请帮助我摆脱这个问题。

【问题讨论】:

    标签: asp.net sql-server crystal-reports odbc database-connection


    【解决方案1】:

    在您上面的代码中,您如何准确地使用存储在配置文件中的 ODBC 连接?例如 [Is it a DataSet?],因为,如果是的话!然后你在加载报告之前关闭数据库连接,就像在这一行之前一样,这里:

    cryRpt.Load(Server.MapPath("~/Reports/Report001.rpt"));
    

    我认为您的问题在于数据库与应用程序的连接本身,而不是 Crystal Reports 组件。 尝试在处理查看器 CrystalReportViewer1.Dispose(); 之前关闭连接 Connection.Close,但要小心:

    不要对 Connection、DataReader 或任何其他对象调用 Close 或 Dispose 类的 Finalize 方法中的其他托管对象。在一个 终结器,你应该只释放你的类的非托管资源 直接拥有。如果您的班级不拥有任何非托管资源,请执行 不要在类定义中包含 Finalize 方法。更多 信息,请参阅垃圾收集。 source

    另外,你的情况很自然,因为客户端保持连接打开,read this too

    这是我使用的代码示例(没有 ODBC 和 MS-Access):

    Imports CrystalDecisions.CrystalReports.Engine
    Imports System.Data.OleDb
    Imports CrystalDecisions.Shared
    
    Public Class CrystalForm
        Dim cryRpt As New ReportDocument
        Dim crtableLogoninfos As New TableLogOnInfos
        Dim crtableLogoninfo As New TableLogOnInfo
        Dim crConnectionInfo As New ConnectionInfo
        Dim CrTables As Tables
        Dim CrTable As Table
        Private Sub CrystalForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim CMDSelect As String = ("SELECT * FROM Table_Name")
            Try
                Using DT As New DataTable
                    Using CN As New OleDbConnection With {.ConnectionString = GetBuilderCNString()}
                        CN.Open()
                        Using DataAdapt As New OleDbDataAdapter(CMDSelect, CN)
                            DataAdapt.Fill(DT)
                        End Using
                    End Using
                    cryRpt.Load(IO.Path.Combine(Application.StartupPath, "Crystal_Report.rpt"))
                    AssignConnection(cryRpt)
                    cryRpt.SetDataSource(DT)
                    CrystalReportViewer1.ReportSource = cryRpt
                End Using
            Catch ex As EngineException
                MsgBox("Report Load Error : " & ex.Message)
            End Try
        End Sub
        Private Sub AssignConnection(rpt As ReportDocument)
            Try
                Dim ThisConnection As New ConnectionInfo()
                With ThisConnection
                    .DatabaseName = ""
                    .ServerName = ""
                    .UserID = "admin"
                    .Password = "MyPassWord"
                End With
                For Each table As Table In rpt.Database.Tables
                    AssignTableConnection(table, ThisConnection)
                Next
                For Each section As Section In rpt.ReportDefinition.Sections
                    For Each reportObject As ReportObject In section.ReportObjects
                        If reportObject.Kind = ReportObjectKind.SubreportObject Then
                            Dim subReport As SubreportObject = DirectCast(reportObject, SubreportObject)
                            Dim subDocument As ReportDocument = subReport.OpenSubreport(subReport.SubreportName)
                            For Each table As Table In subDocument.Database.Tables
                                AssignTableConnection(table, ThisConnection)
                            Next
                            subDocument.SetDatabaseLogon(ThisConnection.UserID,
                                                         ThisConnection.Password,
                                                         ThisConnection.ServerName,
                                                         ThisConnection.DatabaseName)
                        End If
                    Next
                Next
                rpt.SetDatabaseLogon(ThisConnection.UserID,
                                     ThisConnection.Password,
                                     ThisConnection.ServerName,
                                     ThisConnection.DatabaseName)
            Catch ex As EngineException
                MsgBox("Load Report Error : " & ex.Message)
            End Try
        End Sub
        Private Sub AssignTableConnection(ByVal table As Table, ByVal connection As ConnectionInfo)
            Try
                Dim logOnInfo As TableLogOnInfo = table.LogOnInfo
                connection.Type = logOnInfo.ConnectionInfo.Type
                logOnInfo.ConnectionInfo = connection
                With table.LogOnInfo.ConnectionInfo
                    .DatabaseName = connection.DatabaseName
                    .ServerName = connection.ServerName
                    .UserID = connection.UserID
                    .Password = connection.Password
                    .Type = connection.Type
                End With
                table.ApplyLogOnInfo(logOnInfo)
            Catch ex As EngineException
                MsgBox("Load Table Error : " & ex.Message)
            End Try
        End Sub
    End Class
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-10
      • 1970-01-01
      • 2014-12-22
      • 2013-06-28
      • 2011-10-22
      • 1970-01-01
      相关资源
      最近更新 更多