【问题标题】:Local report rdlc to pdf very slow本地报告rdlc到pdf很慢
【发布时间】:2023-03-13 06:06:01
【问题描述】:

有什么方法可以提高本地报告的性能,或者如果没有的话,还有其他方法吗?下面将 rdlc 转换为 pdf 的当前代码。一段时间以来一直在寻找解决方案,但普遍的共识似乎是它的速度很慢,感谢您的帮助。

  public byte[] genReportBytes(int id, string fromm, string too, string           filetype)
{
    reportDetails repD = new reportDetails();
    repD = getOneReport(id);

    LocalReport report = new LocalReport();

    if (fromm != null)
        repD.ParametersCommandLine = "@startdate=" + fromm;

    if (too != null)
        repD.ParametersCommandLine += " @enddate=" + too;

    string RDLCPath = ConfigurationManager.AppSettings["RDLCPath"];
    string ReportOutputPath = ConfigurationManager.AppSettings["ReportOutputPath"];

    string RDLCName = repD.RDLCName;
    RDLCPath += @"\" + RDLCName;
    report.ReportPath = RDLCPath;

    string sqlGet = repD.SQLOfReport;

    report.DataSources.Add(new ReportDataSource(repD.DatasetName, getReportData(sqlGet, repD.ParametersCommandLine)));

    // export to byte array

    Warning[] warnings;
    string[] streamids;
    string mimeType;
    string encoding;
    string filenameExtension;
    string deviceInf = "";
    byte[] bytes;
    string extension;

    if (filetype == "pdf")
    {
        deviceInf = "<DeviceInfo><PageHeight>8.5in</PageHeight><PageWidth>11in</PageWidth><MarginLeft>0in</MarginLeft><MarginRight>0in</MarginRight></DeviceInfo>";
        //fileName = ReportOutputPath + @"\" + repD.NameOfOutputPDF + ".PDF";
        bytes = report.Render("pdf", deviceInf, out mimeType, out encoding, out filenameExtension,
        out streamids, out warnings);
    }
    else
    {
        //fileName = ReportOutputPath + @"\" + repD.NameOfOutputPDF + ".XLS";
        bytes = report.Render(
              "Excel", null, out mimeType, out encoding,
               out extension,
              out streamids, out warnings);
    }

    return bytes;
}

【问题讨论】:

  • 这两行ParametersCommandLine 让我怀疑您的代码可能容易受到SQL Injection 的攻击。你的getReportData 方法是什么样的?
  • 如果您在基于 .NET 4.5 in ASP.NET 的应用程序中使用而不大量使用 动态类型进行序列化和反序列化。也许可以使用&lt;trust legacyCasModel="true" level="Full"/&gt;
  • @Kiquenet 代码审查代表审查工作代码,也可以要求性能改进。很好的例子:codereview.stackexchange.com/questions/104879/…
  • @chillworld 不错,性能改进不一样性能问题?
  • Adrian Nichols 在 github.com/AdrianNichols/ssrs-non-native-functions/blob/… Keys 中有一个帮助代码:RenderReportToMemoryAsPDFInAnotherAppDomain 方法和ReportHelperInAppDomain类

标签: c# rdlc


【解决方案1】:

我已经在这里发布了答案slow-performance-with-dynamic-grouping-and-reportviewer-in-local-mode

基本上你必须在单独的 Appdomain 中运行 reportviewer,这是 Render 方法,它从你当前的 reportviewer 控件中获取所有参数。

private static byte[] Render(string reportRenderFormat, string deviceInfo, string DisplayName, string ReportPath, bool Visible, ReportDataSourceCollection DataSources, string repMainContent, List<string[]> repSubContent, ReportParameter[] reportParam)
{
    AppDomainSetup setup = new AppDomainSetup { ApplicationBase = Environment.CurrentDirectory, LoaderOptimization = LoaderOptimization.MultiDomainHost };
    setup.SetCompatibilitySwitches(new[] { "NetFx40_LegacySecurityPolicy" });
    AppDomain _casPolicyEnabledDomain = AppDomain.CreateDomain("Full Trust", null, setup);
    try
    {
        WebReportviewer.FullTrustReportviewer rvNextgenReport2 = (WebReportviewer.FullTrustReportviewer)_casPolicyEnabledDomain.CreateInstanceFromAndUnwrap(typeof(WebReportviewer.FullTrustReportviewer).Assembly.CodeBase, typeof(WebReportviewer.FullTrustReportviewer).FullName);
        rvNextgenReport2.Initialize(DisplayName, ReportPath, Visible, reportParam, reportRenderFormat, deviceInfo, repMainContent, repSubContent);

        foreach (ReportDataSource _ReportDataSource in DataSources)
        {
            rvNextgenReport2.AddDataSources(_ReportDataSource.Name, (DataTable)_ReportDataSource.Value);
        }

        return rvNextgenReport2.Render(reportRenderFormat, deviceInfo);
    }
    finally
    {
        AppDomain.Unload(_casPolicyEnabledDomain);
    }
}

这是运行报告的新程序集:

namespace WebReportviewer
{
    [Serializable]
    public class FullTrustReportviewer : MarshalByRefObject
    {
        private ReportViewer FullTrust;        
        public FullTrustReportviewer() 
        {
            FullTrust = new ReportViewer();
            FullTrust.ShowExportControls = false;
            FullTrust.ShowPrintButton = true;
            FullTrust.ShowZoomControl = true;
            FullTrust.SizeToReportContent = false;
            FullTrust.ShowReportBody = true;
            FullTrust.ShowDocumentMapButton = false;
            FullTrust.ShowFindControls = true;
           FullTrust.LocalReport.SubreportProcessing += LocalReport_SubreportProcessing;               
        }

        public void Initialize(string DisplayName, string ReportPath, bool Visible, ReportParameter[] reportParam, string reportRenderFormat, string deviceInfo, string repMainContent, List<string[]> repSubContent)
        {
            FullTrust.LocalReport.DisplayName = DisplayName;
            FullTrust.LocalReport.ReportPath = ReportPath;
            FullTrust.Visible = Visible;
            FullTrust.LocalReport.LoadReportDefinition(new StringReader(repMainContent)); 
            FullTrust.LocalReport.SetParameters(reportParam);

            repSubContent.ForEach(x =>
            {
                FullTrust.LocalReport.LoadSubreportDefinition(x[0], new StringReader(x[1]));
            });
            FullTrust.LocalReport.DataSources.Clear();
        }       

        public byte[] Render(string reportRenderFormat, string deviceInfo)
        {
            return FullTrust.LocalReport.Render(reportRenderFormat, deviceInfo);
        }
        public void AddDataSources(string p, DataTable datatable)
        {
            FullTrust.LocalReport.DataSources.Add(new ReportDataSource(p, datatable));
        }

        public SubreportProcessingEventHandler SubreportProcessing { get; set; }

        public static void LocalReport_SubreportProcessing(object sender, SubreportProcessingEventArgs e)
        {
            LocalReport lr = (LocalReport)sender;

            e.DataSources.Clear();
            ReportDataSource rds;

            if (e.ReportPath.Contains("DataTable2"))
            {
                DataTable dt = (DataTable)lr.DataSources["DataTable2"].Value;
                DataView dv = new DataView(dt);
                dv.RowFilter = string.Format("Id={0}", e.Parameters["Id"].Values[0]);
                rds = new ReportDataSource("DataTable2", dv.ToTable());
                e.DataSources.Add(rds);
            }
        }
    }
}

这样做只需要对您当前的代码进行最少的更改。 问候。

【讨论】:

  • 嗨。我得到:“对象必须实现 IConvertible。”在“参数类型'Microsoft.Reporting.WinForms.ReportParameter[]'不能转换成参数类型'Microsoft.Reporting.WinForms.ReportParameter[]”中。
  • 对不起@zchpit 这个解决方案是针对WebForms的,我没有在WinForms上测试过。
  • 为我工作,但我不确定如何使用您的代码示例。我如何处理返回的字节数组?如何获取 Web 表单页面来呈现它?
  • @andrej351 您对报告执行相同操作,此方法采用与您的报告查看器相同的参数:reportBytes = genReport.LocalReport.Render("PDF"); //这里用上面的方法替换 Response.ContentType = "application/pdf"; Response.AddHeader("Content-Disposition", string.Format("inline; filename='{0}'", genReport.LocalReport.DisplayName)); Response.AddHeader("内容长度", reportBytes.Length.ToString()); Response.BinaryWrite(reportBytes);
  • @montelof 谢谢,听起来它可以将 PDF 呈现给响应。但是,我有一个 Web 窗体页面(包括导航、报表参数的服务器控件等),一个在 ASPX 标记中呈现本地报表的报表查看器服务器控件。你知道这是否可能吗?
【解决方案2】:

此外,将&lt;trust legacyCasModel="true" level="Full"/&gt; 放在&lt;system.web&gt; 标记内web.config 将产生相同的结果。 More details here

【讨论】:

    【解决方案3】:

    听起来没有办法将此 RDLC 改进为 PDF。没办法!

    【讨论】:

      猜你喜欢
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多