What you will learn
- What is the ICachedReport interface.
- System generated classes and when to modify them.
- Adding extensions to support ConnectionInfo binding.
- Putting it all together.
|
namespace Optimized.Reports { using
System; using
CrystalDecisions.ReportSource; public class SalesDirectory : ReportClass {…} [System.Drawing.ToolboxBitmapAttribute(typeof(CrystalDecisions.Shared.ExportOptions), "report.bmp")] public class CachedSalesDirectory : Component, IcachedReport {…} } |
What you will often find is that if the report is not properly authenticated, it will prompt the user everytime the report is loaded. What we will do here is leverage the ConnectionInfo object and create an extension method for the Tables inside the report.
|
using
CrystalDecisions.CrystalReports.Engine; using
CrystalDecisions.Shared; namespace Core.Util { public static class Extensions { /// <summary> /// Set Crystal Report ConnectionInfo. /// </summary> /// <param
name="tables">CrystalDecisions.CrystalReports.Engine.Tables</param> public
static void
SetLocation(this Tables
tables) { ConnectionInfo
connectionInfo = new ConnectionInfo(); connectionInfo.ServerName = ConfigurationManager.AppSettings["CrystalServerName"].ToString(); connectionInfo.DatabaseName = ConfigurationManager.AppSettings["CrystalDatabaseName"].ToString(); connectionInfo.UserID = ConfigurationManager.AppSettings["CrystalUserID"].ToString(); connectionInfo.Password = ConfigurationManager.AppSettings["CrystalPassword"].ToString(); connectionInfo.IntegratedSecurity
= Convert.ToBoolean( ConfigurationManager.AppSettings["CrystalIntegratedSecurity"]); foreach
(CrystalDecisions.CrystalReports.Engine.Table
table in tables) { TableLogOnInfo
tableLogOnInfo = table.LogOnInfo; tableLogOnInfo.ConnectionInfo
= connectionInfo;
table.ApplyLogOnInfo(tableLogOnInfo); } } } } |
Now that we have our SalesDirectory report with the wrapper and utility class, we are going to create a page to hold a report viewer. Below is the code listing for adding the directive to the page and immediately after the declaration for the control.
|
<%@
Register assembly="CrystalDecisions.Web, Version=13.0.2000.0,
Culture=neutral, PublicKeyToken=692fbea5521e1304" namespace="CrystalDecisions.Web"
tagprefix="CR"
%> <CR:CrystalReportViewer ID="CrystalReportViewer"
runat="server" AutoDataBind="true" Visible="true" /> |
|
// Without Caching -
To be able to compare performance differences. private void DisplayDirectoryReport() { SalesDirectory
directoryReport = new SalesDirectory();
directoryReport.Database.Tables.SetLocation(); // Set Connection // Set the location for any subreport foreach
(CrystalDecisions.CrystalReports.Engine.ReportDocument
rDocument in directoryReport.Subreports)
rDocument.Database.Tables.SetLocation(); CrystalReportViewer.ReportSource =
directoryReport; CrystalReportViewer.DataBind(); } |
|
// Implementing the
caching management class. private void DisplayDirectoryReport() { Reports.CachedSalesDirectory
cachedSalesDirectory = new Reports.CachedSalesDirectory(); // Extra step
(part of the interface and for the most part will have all the code // needed.
cachedSalesDirectory.CreateReport(); CrystalReportViewer.ReportSource =
cachedSalesDirectory; CrystalReportViewer.DataBind(); } // Inside CachedSalesDirectory
code in red is the code that needs to be added. public virtual CrystalDecisions.CrystalReports.Engine.ReportDocument CreateReport() { SalesDirectory rpt = new
SalesDirectory(); rpt.Site = this.Site; rpt.Database.Tables.SetLocation(); foreach
(CrystalDecisions.CrystalReports.Engine.ReportDocument rDocument in rpt.Subreports)
rDocument.Database.Tables.SetLocation(); return rpt; } |
|
[System.Drawing.ToolboxBitmapAttribute(typeof(CrystalDecisions.Shared.ExportOptions), "report.bmp")] public class CachedSalesDirectory
: Component, ICachedReport
{ public string
Counties { get; set;
} public
int StateID { get;
set; } …} |
Next
step is to set the new properties before calling create.
|
// Implementing the
caching management class. private void DisplayDirectoryReport(string counties, int StateID) { Reports.CachedSalesDirectory
cachedSalesDirectory = new Reports.CachedSalesDirectory(); cachedSalesDirectory.Counties
= counties; cachedSalesDirectory.StateID = StateID; cachedSalesDirectory.CreateReport(); CrystalReportViewer.ReportSource =
cachedSalesDirectory; CrystalReportViewer.DataBind(); } |
Finally
we will change the CreateReport function to account for the parameters.
|
// Inside CachedSalesDirectory
code in red is the code that needs to be added. public virtual CrystalDecisions.CrystalReports.Engine.ReportDocument CreateReport() { SalesDirectory rpt = new
SalesDirectory(); rpt.Site = this.Site; rpt.SetParameterValue("@Counties",
Counties); rpt.SetParameterValue("@StateID",
StateID); foreach
(CrystalDecisions.CrystalReports.Engine.ReportDocument
rDocument in rpt.Subreports)
rDocument.Database.Tables.SetLocation(); return rpt; } |
Implementing both solutions will prove the efficiency of leveraging the caching functionality.

Manish SinghPosted Nov 23, 2011, 12:10 PM
Hi.... It,s really help for me i am waiting for next article.
Mahesh ChandPosted Feb 13, 2011, 4:49 PM
Good advanced. Like it. Thanks Felipe.