2015-05-28 5 views
4

Есть ли способ улучшить производительность локального отчета или даже альтернативы, если нет? Текущий код для преобразования rdlc в pdf ниже. Ищете решение в течение довольно долгого времени, но общий консенсус, похоже, заключается в том, что он просто медленный, спасибо за любую помощь.Локальный отчет 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; 
} 
+0

Эти две строки 'ParametersCommandLine' заставляют меня подозревать, что ваш код может быть уязвим для [SQL Injection] (http://www.troyhunt.com/2013/07/everything-you-wanted-to-know-about- sql.html). Как выглядит ваш метод getReportData? –

+0

Если вы используете ***. NET 4.5 в приложении ASP.NET *** без особого использования _динамических типов для сериализации и десериализации. Может быть, можно использовать '' – Kiquenet

+1

@Kiquenet Code review означает просмотр рабочего кода, также могут потребоваться улучшения производительности. Приятный пример: http://codereview.stackexchange.com/questions/104879/creating-a-numeric-phone-keypad/104882#104882 – chillworld

ответ

5

Я пост ответ здесь slow-performance-with-dynamic-grouping-and-reportviewer-in-local-mode

В основном вы должны запустить ReportViewer в отдельном AppDomain, это метод визуализации, он принимает все параметры из текущего управления 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); 
      } 
     } 
    } 
} 

Действовать таким образом потребует минимальных изменений в текущий код. Отношения.

+1

Привет. Я получаю: «Объект должен реализовывать IConvertible». в «Тип аргумента» Microsoft.Reporting.WinForms.ReportParameter [] 'не может быть преобразован в тип параметра «Microsoft.Reporting.WinForms.ReportParameter []». – zchpit

+0

sorry @zchpit Это решение для WebForms, я не тестировал его на WinForms. – montelof

+1

работал для меня, но я не уверен, как использовать пример кода. Что мне делать с возвратом массива байтов? Как получить страницу веб-форм для ее рендеринга? – andrej351

Смежные вопросы