在分布式环境中使用RDLC的最佳实践

时间:2010-08-24 13:51:18

标签: rdlc dynamic-rdlc-generation

我的公司有一个Windows窗体应用程序,它利用ClickOnce和.NET Remoting(很快就是WCF)到一个处理所有数据访问操作的后端IIS Web应用程序。对于报告,我们当前使用SSRS并使分布式客户端直接连接到报告服务器。

我们希望通过RDLC文件支持本地报告,从而可能删除或扩充我们对SSRS报告的依赖性。我必须克服的一个障碍是,单个客户端计算机不太可能直接访问数据库,因此需要通过我们的远程处理或WCF传输层从Web应用程序获取报告数据。

为了动态构建报表参数提示的UI而“发现”报表的参数我认为并不是非常困难,但实际上告诉后端系统要调用哪个类/方法以便返回报告的正确数据不那么简单。

是否有人尝试以某种方式将信息嵌入到RDLC文件中(通过报告中的注释或其他方式),可以将其用作服务器应用程序层的“提示”以确定要执行的方法?实际的RDLC可能会存储在数据库中,而不是与我们的应用程序一起分发。

任何见解或指导都将受到赞赏。

-MrB

1 个答案:

答案 0 :(得分:1)

查看www.gotreportviewer.com和RDL查看器示例(右侧的最后一个示例)。它已经有了加载RDLC并解析XML文件以获取参数以及连接信息和查询信息的代码。有了这个,您应该能够使用后端获取所有内容并填充/加载报告并运行它。

至于在某个地方的RDLC中添加提示或注释以指定要建立的调用,我建议也许仅使用报告名称作为提示。我们过去已经完成了这项工作,因为我们的报告知道要加载数据的内容。

我们之前做过类似的事情:

VB版:

Select Case GetReportName()

            Case "SiteEval"
                Using adp As New DataSetsTableAdapters.SiteEvalTableAdapter, _
                 objDT As New DataSets.SiteEvalDataTable
                    adp.Fill(objDT)
                    objLR.DataSources.Add(New ReportDataSource("DataSets_SiteEval", objDT))
                End Using
            Case ....

C#版本:

switch (GetReportName()) {

    case "SiteEval":
        using (DataSetsTableAdapters.SiteEvalTableAdapter adp = new DataSetsTableAdapters.SiteEvalTableAdapter()) {
            using (DataSets.SiteEvalDataTable objDT = new DataSets.SiteEvalDataTable()) {
                adp.Fill(objDT);
                objLR.DataSources.Add(new ReportDataSource("DataSets_SiteEval", objDT));
            }
        }

        break;

利用我们的XSD和数据集来加载我们的报告。在这种情况下,我们的本地报告可以访问数据库。在您的情况下,您可以采用这个想法,并使用您自己返回的数据表从调用服务中填充数据集。如果您有大量报告,这不是最优雅或最容易维护的。

在我们的例子中,我们现在正在使用RDL Viewer示例并根据我们的需要对其进行修改,以便不需要上面的代码。我们将传递路径到RDLC文件,代码将通过读取RDLC的xml来加载所需的内容。但是,在这种情况下,本地报告可以访问数据库。我认为修改它以使用上述代码构思从外部源获取数据或者像我们现在那样修改www.gotreportviewer.com中的RDL Viewer示例并不困难。

修改了RDL Viewer示例后,我们现在有一些类似的东西(仍然正在运行......)代码在VB中。

    Dim r As New Report(Server.MapPath("App_Reports/" & GetReportName() & ".rdlc"), GetReportName())

    Dim p As ReportParameterInfoCollection = r.GetParameters() 'read only....
    If p.Count > 0 Then
        Dim rptParams(p.Count - 1) As ReportParameter
        Dim i As Integer = 0
        For Each param In p
            rptParams(i) = New ReportParameter(param.Name)
            rptParams(i).Values.Add("99999999")
            i += 1
        Next
        r.SetParameters(rptParams)
    End If

    r.LoadReport()

再见丑陋和冗长的转换声明。再见,需要知道如何加载报告.... 现在,如果我们能够弄清楚如何更好地处理参数....这段代码是当前正在进行的工作,但RDL Viewer样本让我们很快就开始了....

我也正在玩反射做同样的事情。我发现这篇文章让反射工作变得轻而易举。 http://www.slimee.com/2009/09/net-using-reflection-to-execute.html

现在您要做的就是传递数据表的字符串,它将生成驱动报告的数据表。由于使用数据集,您将始终知道如何创建名称,您可以轻松使用它。

我认为这两种方法都是解决方案,可以消除丑陋的switch语句,并使代码更易于维护。使用反射,代码要小得多,但可能会慢一些。

两者都有一些神奇的字符串问题。沿着这条线的某个地方,你必须传递一串你想要运行的东西。一个团队可以轻松创建一个容易解决的约定....