在 Crystal 中设置报告源 .Net 报告在 crdb_adoplus.dll 中引发 NullReferenceException

Setting Report Source in Crystal Report for .Net throws a NullReferenceException in crdb_adoplus.dll

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

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

加载项提供的 WPF 控件中有一个 Crystal 报表查看器控件。到目前为止,一切正常。我可以在我的加载项中创建几乎任何 WPF 控件,并且它在主机应用程序中完美运行。一旦我尝试将报告附加到查看器,这就会崩溃。

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

我使用 .Net 对象创建了一个 XML 文档,报告是针对该文档设计的。这工作正常,让我可以通过我的报告并在主机应用程序中查看它。这就是我现在被困的地方。 每当我尝试为报告提供数据源时 Crystal 报告会在 SAP 的 DLL crdb_adoplus.dll 中抛出一个空引用异常,并且没有指示是什么原因导致的例外。我的所有对象都已正确实例化,包括报表、查看器、wpf 元素宿主和 wpf 控件。我的数据集使用 entity framework 提供,正在转换为数据集,因此其中没有可空类型,只有 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 数据集,这样我就可以摆脱 XML 问题?

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

在此先感谢您的帮助。

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

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

所以我更改了这段代码:

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

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

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

希望这对以后的其他人有所帮助。