在Crystal Report for .Net中设置报表源会在crdb_adoplus.dll中引发NullReferenceException

时间:2016-04-07 17:05:31

标签: wpf winforms remoting crystal-reports-xi system.addin

使用Crystal Reports XI for dot net时,我遇到了一个非常奇怪的异常。我目前正在VB.Net中为企业应用程序开发报表服务。该服务使用System.AddIn (aka Managed Add-in Framework or MAF)作为插件/加载项托管在主应用程序中。主应用程序使用Win Forms,并将托管由我的加载项在WPFElementHost中提供的控件。

加载项位于其自己的应用程序域中,并使用NativeHandleContracts从加载项应用程序域将WPF控件传递到主机应用程序域,它们在运行时绑定到WPFElementHost。

加载项提供的WPF控件中包含一个Crystal Report Viewer Control。到目前为止,一切正常。我可以在我的加载项中创建几乎任何WPF控件,它在主机应用程序中完美运行。一旦我尝试向观众附上报告,这就会崩溃。

首先,我尝试使用ADO.Net DataSet作为我的数据模式来构建我的报告。每当这会尝试加载到报表查看器中时,水晶报表就会抛出架构不存在的异常。造成这种情况的原因是,由于某些原因,水晶报告需要查看主机应用程序应用程序域以及架构的命名空间。但是,架构存在于完全不同的应用程序域和命名空间中。我尝试将架构嵌入为资源,并复制本地。没有成功,我继续使用.Net Objects。

使用.Net Objects,我创建了一个针对该报告设计的XML文档。这很好,并允许我传递我的报告并在主机应用程序中查看它。这就是我现在被困住的地方。 每当我尝试为报表提供DataSource时,Crystal Reports会在crdb_adoplus.dll 中抛出一个空引用异常,这是SAP的DLL,并没有告诉我导致该异常的原因。我的所有对象都已正确实例化,报告,查看器,wpf元素主机和wpf控件。我使用实体框架提供的数据集正在转换为DataSet,因此其中没有可空类型,只有dbnull值。这个例外在这一点上没有理由抛出。除了抛出异常之外,没有提供额外的输出。

此外,在此加载过程中,创建的报表对象的部分时间会超时。这将发生,没有任何异常或任何类型的错误抛出。

以下是检索数据,尝试将数据绑定到报表以及将报表绑定到查看器的代码。

        Try
            Dim messages As String = Nothing

            If report Is Nothing Then
                report = New BOMPartsListWithStandard
            End If

            Using conn = BOMReportingService.BOMReportingServiceClient.CreateConnection()
                Dim dataSet As DataSet = conn.Proxy.GetBOMTreePartsListElements(5339, messages).ToDataSet
                report.SetDataSource(dataSet)
            End Using

            reportViewer.ViewerCore.ReportSource = report
            reportViewer.ViewerCore.RefreshReport()
            Debug.WriteLine($"Created and attached report succesfully. With {IIf(String.IsNullOrEmpty(messages), "no messages.", messages)}")
        Catch ex As Exception
            Debug.WriteLine(ex.ToString)
        End Try

report.SetDataSource(dataSet)位代码是抛出异常的地方。

我是否忽略了明显的东西?有没有办法说服Crystal Reports在正确的应用程序域中使用ADO.Net DataSet,这样我就可以摆脱XML问题了?

此加载项需要存在于单独的应用程序域或进程中,以便可以在运行时动态卸载和重新加载。这是系统的要求。它也需要是自包含的,所以我不能在应用程序的主机端做任何事情,它必须在加载项中运行。

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

在挖掘之后,我找到了自己问题的答案。所以我会在这里发布答案,以防其他人遇到类似的问题。

问题似乎在于报告如何解释DataSet对象。出于某种原因,在查找数据时会丢失。所以你必须将它指向实际的第一个表项。

所以我改变了这段代码:

        Using conn = BOMReportingService.BOMReportingServiceClient.CreateConnection()
            Dim dataSet As DataSet = conn.Proxy.GetBOMTreePartsListElements(5339, messages).ToDataSet
            report.SetDataSource(dataSet)
        End Using

我将report.SetDataSource(dataSet)替换为report.SetDatSource(dataSet.Tables(0))。所以现在它看起来像这样

        Using conn = BOMReportingService.BOMReportingServiceClient.CreateConnection()
            Dim dataSet As DataSet = conn.Proxy.GetBOMTreePartsListElements(5339, messages).ToDataSet
            report.SetDataSource(dataSet.Tables(0))
        End Using

希望将来可以帮助其他人。