我们有一个Asp.Net页面,它针对后端的Oracle运行report,这在导出到Excel电子表格时非常慢。我已经做了一些调查,并确定查询本身不应该受到责备--我可以使用seconds直接针对Oracle运行查询,并在大约5秒内将结果导出到Excel,但是当我通过asp.net页面和ReportViewer控件运行查询时,返回时间大约需要3分钟。
有谁有什么建议来解释为什么这么慢?这个查询返回大约8000行,每个行大约有30列,所以它不是一个很小的结果集,但它也不是很大。任何关于我们如何优化报告的建议都将不胜感激。
我正在使用Microsoft.ReportViewer.WebForms版本10.0.0.0,有人知道v11是否有性能改进吗?
编辑:尝试了ReportViewer v11,没有提高速度。
发布于 2015-09-14 05:17:55
如果您的报告中有分组。从.NET 4开始,当遗留CAS被移除时,本地处理的RDLC报告需要花费大量时间来执行动态分组或动态过滤器。有一个关于这个https://social.msdn.microsoft.com/Forums/sqlserver/en-US/6d89e2ce-3528-465f-9740-7e22aa7b7aae/slow-performance-with-dynamic-grouping-and-reportviewer-in-local-mode?forum=sqlreportingservices的现有讨论
我找到的最好的解决办法是,
using Microsoft.Reporting.WebForms;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
//As you would expect, the new assembly WebReportviewer.FullTrustReportviewer
//all it does is just run the report. that's it. here is the code, it should be in a separated project:
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;
//FullTrust.LocalReport.SetBasePermissionsForSandboxAppDomain(new PermissionSet(PermissionState.Unrestricted));
}
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);
}
}
}
}
public static byte[] GeneratePBAReport()
{
string l_spName = string.Empty;
string l_reportPath = string.Empty;
var repCol = new List<ReportDataSource>();
var repParCol = new ReportParameter[1];
if (id == "")
{
l_reportPath = HttpContext.Current.Server.MapPath("~\\.rdlc");
l_spName = "";
}
else
{
l_reportPath = HttpContext.Current.Server.MapPath("~\\.rdlc");
l_spName = "";
}
repParCol[0] = new ReportParameter("pID", "");
var ds = new DataSet();
using (var sqlCmd = new SqlCommand(l_spName, new SqlConnection(ConfigurationManager.ConnectionStrings[""].ConnectionString)))
{
sqlCmd.CommandType = CommandType.StoredProcedure;
var sqlParam = new SqlParameter() { Value = "", ParameterName = "" };
sqlCmd.Parameters.Add(sqlParam);
sqlCmd.CommandTimeout = 300;
using (var sqlAdapter = new SqlDataAdapter(sqlCmd))
{
sqlAdapter.Fill(ds);
}
}
var rds = new ReportDataSource();
rds.Name = "";
rds.Value = ds.Tables[0];
//l_report.DataSources.Add(rds);
repCol.Add(rds);
rds = new ReportDataSource();
rds.Name = "";
rds.Value = ds.Tables[1];
//l_report.DataSources.Add(rds);
repCol.Add(rds);
rds = new ReportDataSource();
rds.Name = "";
rds.Value = ds.Tables[2];
//l_report.DataSources.Add(rds);
repCol.Add(rds);
rds = new ReportDataSource();
rds.Name = "";
rds.Value = ds.Tables[3];
//l_report.DataSources.Add(rds);
repCol.Add(rds);
Warning[] warnings;
string[] streamids;
string mimeType;
string encoding;
string extension;
string deviceInfo;
deviceInfo = "<DeviceInfo><SimplePageHeaders>True</SimplePageHeaders></DeviceInfo>";
return NewDomainReport.Render("PDF", deviceInfo, "-" , l_reportPath, true, repCol, string.Empty, new List<string[]>(), repParCol);
}
为了进行真正快速的测试,您可以尝试像本文中提到的那样在web.config中添加CAS。
在ASP.NET应用程序中,可以在<trust legacyCasModel="true" level="Full"/>
文件的system.web部分使用web.config实现相同的结果。
如果速度显着提高,上述代码的行为将相同。以上代码的好处是创建一个单独的AppDomain,而不是影响整个解决方案。
发布于 2019-05-06 14:24:11
添加<trust legacyCasModel="true" level="Full"/>
对我来说不是一个选项,因为我在代码中使用dynamic
类型。
此代码正在工作:
public class CustomReportRenderer
{
public static byte[] RenderReport(string reportPath, string rdlcDSName, DataTable rdlcDt, ReportParameter[] rptParams, string downloadFormat, out string mimeType, out string filenameExtension)
{
var assemblyDir = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath);
AppDomainSetup setup = new AppDomainSetup()
{
ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile,
LoaderOptimization = LoaderOptimization.MultiDomainHost,
PrivateBinPath = assemblyDir
};
setup.SetCompatibilitySwitches(new[] { "NetFx40_LegacySecurityPolicy" });
AppDomain _casPolicyEnabledDomain = AppDomain.CreateDomain("Full Trust", null, setup);
try
{
FullTrustReportviewer rpt = (FullTrustReportviewer)_casPolicyEnabledDomain.CreateInstanceFromAndUnwrap(typeof(FullTrustReportviewer).Assembly.CodeBase, typeof(FullTrustReportviewer).FullName);
rpt.Initialize(reportPath, rptParams);
var bytes = rpt.Render(rdlcDSName, rdlcDt, downloadFormat, out mimeType, out filenameExtension);
return bytes;
}
finally
{
AppDomain.Unload(_casPolicyEnabledDomain);
}
}
}
[Serializable]
public class FullTrustReportviewer : MarshalByRefObject
{
private ReportViewer FullTrust;
public FullTrustReportviewer()
{
FullTrust = new ReportViewer();
FullTrust.ProcessingMode = Microsoft.Reporting.WebForms.ProcessingMode.Local;
}
public void Initialize(string reportPath, ReportParameter[] rptParams)
{
FullTrust.LocalReport.ReportPath = reportPath;
FullTrust.LocalReport.SetParameters(rptParams);
}
public byte[] Render(string rdlcDSName, DataTable rdlcDt, string downloadFormat, out string mimeType, out string filenameExtension)
{
Warning[] warnings;
string[] streamids;
string encoding;
FullTrust.LocalReport.DataSources.Add(new ReportDataSource(rdlcDSName, rdlcDt));
var bytes = FullTrust.LocalReport.Render(downloadFormat, null, out mimeType, out encoding, out filenameExtension, out streamids, out warnings);
return bytes;
}
}
从aspx或mvc控制器方法调用RenderReport
方法
var bytes = CustomReportRenderer.RenderReport(rdlcFileFullPath, "ReportsDataSet", ds.Tables[0], rptParams, downloadFormat, out mimeType, out extension);
// Now that you have all the bytes representing the PDF report, buffer it and send it to the client.
Response.Buffer = true;
Response.Clear();
Response.ContentType = mimeType;
Response.AddHeader("content-disposition", "attachment; filename=" + fileName + "." + extension);
Response.BinaryWrite(bytes); // create the file
Response.Flush(); // send it to the client to download
发布于 2019-01-24 23:13:00
可能要归咎于简单的表达式和条件格式。
我们的一份报告在大数据(2万多行)方面有一个非常类似的问题。查询正在快速返回数据,但是生成到屏幕的速度很慢,导出到excel的速度更慢。使用报表查看器10和12的问题是相同的。
令我惊讶的是,删除tablix排序、日期格式表达式和交替背景行颜色表达式使该报告生成速度快得多,导出excel的时间从超过半小时延长到大约一分钟。
https://stackoverflow.com/questions/23787853
复制相似问题