【发布时间】:2016-04-07 17:05:30
【问题描述】:
我在使用 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 控件。到目前为止,一切正常。我可以在我的加载项中创建几乎任何 WPF 控件,并且它在主机应用程序中完美运行。一旦我尝试将报告附加到查看器,这就会崩溃。
首先,我尝试使用 ADO.Net DataSet 作为我的数据架构来构建我的报告。每当这将尝试加载到报表查看器中时,水晶报表都会抛出架构不存在的异常。这是因为由于某种原因水晶报告想要查看主机应用程序应用程序域以及模式的命名空间。但是,架构存在于完全不同的应用程序域和命名空间中。我尝试将模式嵌入为资源,并复制本地。没有成功,我转而使用 .Net Objects。
使用 .Net Objects,我创建了一个用于设计报告的 XML 文档。这工作得很好,让我可以通过我的报告并在主机应用程序中查看它。这就是我现在卡住的地方。 每当我尝试为报表提供数据源时,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 数据集,这样我就可以摆脱 XML 问题?
此加载项需要存在于单独的应用程序域或进程中,以便可以在运行时动态卸载和重新加载。这是对系统的要求。它还需要是自包含的,所以我不能在应用程序的主机端做任何事情,这一切都必须在外接程序中运行。
提前感谢您的帮助。
【问题讨论】:
-
作为补充说明,ToDataSet 是一个通用扩展,可将 IList 集转换为 DataSet。这工作得很好,需要将 Entity Framework Nullable 类型转换为 DBNull.Values。
标签: wpf winforms remoting crystal-reports-xi system.addin