on 09-22-2008 4:35 PM
I have Created a common page that has a CrystalReportViewerControl (name of this page is ShowReport.aspx). The report name and database name that required for the report is being passed in a querystring. The database connection info is being pulled from the web.config file. All of the reports that I am dealing with have dynamic parameters and the Crystal Prompt page is automatically being created by the crystal viewer for these. Everything in my application is working fine except that when I try to access any report for the 76th. time I get the following error "The maximum report processing jobs limit configured by your system administrator has been reached."
I have already researched this error and am aware that the PrintJobLimit can be modifed to increase this limit or can be set to -1 if we need to allow unlimited connections. However doing this is not an option due to the degradation of server performance.
The other option that I have tried is to make sure I close and dispose of the report document object on the Page_unload or the page_SavedStateComplete() however on doing so even the session variable that I am using to store the originally created reportdocument is loosing all of the values it requires to display the report. The session variable is still available i.e. it is still of type report document but it has no values for any of the properties like FileName, database etc , basically for all of those properties it show an error "Invalid File Path" when viewed in debug mode.
I have already tried several approaches but with no luck. Every single time I close the originally created ReportDocument object I loose all the required values in the Session
I am using Crystal Report XI R2 , .Net 2.0 and ASP.net
Following is the code: (Any help will be highly appreciated) Thanks:
Option Strict On
Imports CrystalDecisions.CrystalReports.Engine
Imports CrystalDecisions.Shared
Imports System.Data.SqlClient
Imports System.IO
Partial Class _ShowReport
Inherits System.Web.UI.Page
Private FechReport As ReportDocument
Dim strSelectedDatabase As String
Dim strReportsFolderPath As String =
System.Configuration.ConfigurationManager.AppSettings("ReportsFolderPath").ToString()
Dim strReportFileName As String
Dim strReportFullPath As String
Dim iInsertedLogId As Integer 'This variable is used to store the inserted log id for the executed report.
Dim strConnString As String = System.Configuration.ConfigurationManager.AppSettings("ConnString").ToString()
Dim strServerName As String = System.Configuration.ConfigurationManager.AppSettings("CR_ServerName").ToString()
Dim strUserName As String = System.Configuration.ConfigurationManager.AppSettings("CR_UserName").ToString()
Dim strPassword As String = System.Configuration.ConfigurationManager.AppSettings("CR_Password").ToString()
Protected Sub Page_OnSaveStateComplete(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.SaveStateComplete
If IsPostBack Then
If iInsertedLogId > 0 Then
UpdateReportLog_ReportServedTime(iInsertedLogId)
If Not FechReport Is Nothing Then
FechReport.Close()
End If
End If
End If
End Sub
Sub Page_Unload(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Unload
If Not FechReport Is Nothing Then
'FechReport.Close()
'FechReport.Dispose()
'GC.Collect()
End If
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim sRptFileName As String
If Request.QueryString("database") "" Then
strSelectedDatabase = Request.QueryString("database")
Else
Response.Write("A Valid Database has not been supplied to this page")
Response.End()
End If
If Request.QueryString("ReportFileName") "" Then
strReportFileName = Request.QueryString("ReportFileName")
strReportFullPath = strReportsFolderPath & strReportFileName
Else
Response.Write("A Valid Report has not been supplied to this page")
Response.End()
End If
sRptFileName = strReportFullPath
If Not IsPostBack Then
FechReport = New ReportDocument
If Not FechReport Is Nothing Then
ShowReport(sRptFileName)
End If
Else
If (Session("oReportDocument") Is Nothing) Then
FechReport = New ReportDocument
ShowReport(sRptFileName)
Else
'FechReport = New ReportDocument
'FechReport = CType(Session("oReportDocument"), ReportDocument)
myCrystalReportViewer.ReportSource = Session("oReportDocument")
'myCrystalReportViewer.ReportSource = FechReport
End If
End If
End Sub
Public Function ShowReport(ByVal strReportFileName As String) As Boolean
Dim blNoErrors As Boolean = True
Dim crDatabase As Database
Dim crTables As Tables
Dim crTable As Table
Dim crTableLogOnInfo As TableLogOnInfo
Dim crConnectionInfo As ConnectionInfo
FechReport.FileName = strReportFileName
myCrystalReportViewer.ReportSource = FechReport
crConnectionInfo = New ConnectionInfo()
With crConnectionInfo
.ServerName = strServerName
.DatabaseName = strSelectedDatabase
.UserID = strUserName
.Password = strPassword
End With
Try
crDatabase = FechReport.Database
crTables = crDatabase.Tables
For Each crTable In crTables
crTableLogOnInfo = crTable.LogOnInfo
crTableLogOnInfo.ConnectionInfo = crConnectionInfo
crTable.ApplyLogOnInfo(crTableLogOnInfo)
Next
Catch ex As Exception
Response.Write(ex.Message & ControlChars.NewLine & ex.InnerException.ToString & ControlChars.NewLine)
Exit Function
End Try
Session("oReportDocument") = FechReport
'FechReport.Close()
'FechReport.Dispose()
'GC.Collect()
Return blNoErrors
End Function
End Class
Hello,
There is a Registry key that limits the number of print jobs that can be handled.
To increase the number of jobs change this key:
HKEY_LOCAL_MACHINE\SOFTWARE\Business Objects\Suite 11.5\Report Application Server\InprocServer - PrintJobLimit = 75
I would do it in minor increments and don't go over 300. It's dependant on the hard ware you have and resources available.
Also, I see in your code you commented out the dispose methods. You must do this to clean up memory and release the jobs.
'FechReport.Close()
'FechReport.Dispose()
'GC.Collect()
Thank you
Don
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks for your reply.
1. Increasing the PrintJob limit is not an option due to performance issues.
2. If I try to close the originally created Reportdocument object the session variable to which it is assigned looses all of it;s values and when viewed in debug mode shows "Invalid File path" for all of it's properties. The type of the session variable is still Report document be with Errors in all of it properties. Hence I have uncommented the lines that close and dispose the original reportdocument.
Last thing you could try is to export your report file to Crystal Reports file in a temporary directory. You can set the report source to this now saved data report.
- Load the saved data ReportDocument in the Load event
- Set the ReportSource of the viewer to the saved data ReportDocument
- Clean up in the Unload event
Also remember that the CR .NET engine is meant for light reporting needs. If you need a robust reporting solution you'll need to build your own performance and fault tolerant mechanisms. Or make the move to Crystal Reports Server or BusinessObjects Enterprise.
I have considered that approach as well and here is the problem. 99% of the reports that I am delivering using my app have Dynamic parameters and we are using the inbuilt Prompt page that the Crystal Viewer shows when the report has parameters. A user may hit the page that shows the prompts page and might frequently not run the report and just go to another report. However in showing the prompts page a connection has already been made. Any attempts to release the original Report Object results in an error on the Prompts page itself. This is the reason why the approach of saving a copy of the report on the webserver did not work for me.
We also have Crystal Enterprise server which is being used for scheduled reports. However we also have an internal website that shows many utilities Reports being one of them within itself and it is required for us to use it for On Demand reports.
Thanks.,
A couple other things you can do to save on print jobs:
- Make user of caching instead of sessions. This will allow you to share the report between multiple users. Keep in mind that reports that implement the ICachedReport class will be shared among users when the database and parameter information is the same.
- https://boc.sdn.sap.com/node/7923
- Add cleanup code to your Session_End event. You may also need to reduce the duration of your user sessions to ensure the reports are cleaned up quickly.
We aren't going to have an easy answer for you here. As I've mentioned before, the CR .NET SDK is designed as a light reporting tool. When you run into errors like "The maximum report processing jobs limit..." you know you are pushing the engine a little to hard. The options are to either build in your own fault tolerant mechanisms, or move your reports to our Enterprise product line.
To add on to David's last response. See the Choose_the_right_SDK.ppt at this link:
https://boc.sdn.sap.com/files/Choose_the_right_SDK.ppt
Ludek
I have looked into Caching the report document as well. However, as you mentioned in the post it, it will only be usefull when the DB and the report parameters remain the same which is not the case in our application. We have multiple identical databases and hundreds of reports. Our users have the option of using a combination of any database and any reports, each report having numerous parameters.
Since one user can only access one report at a time. i do have cleanup code that removes the session variable used to store the reportdocument object in the page that is initially used to call the ShowReport.aspx page.
I understand now that the CR.net SDK is only good for light reporting only. Unfortunately when we started development based on all of the articles that I gathered, I didn't anticipate running to issues like this. But I guess that's the nature of the business :-). And hence there are people like you who go out of the way to answer these difficult questions.
Regards,
I did go through the presentation and was insightfull. From what I understand we are using the right SDK which is CR.net. However I did see something else mentioned which points towards a Crystal enterprise SDK. I will read a little bit more on that and see if it is something that might be of better use to us.
Thanks,
I found the solution to this issue. I have created a ReportFactory class and am queueing the ReportDocuments in that queue. I have set the queue limit to 65. I have posted the full solution as a reply on the asp.net forum since that was where I got the solution to the issue.
here is the link: http://forums.asp.net/p/1322885/2640173.aspx
Would like to Thank everybody who replied to this thread.
Regards,
User | Count |
---|---|
84 | |
10 | |
10 | |
10 | |
7 | |
6 | |
6 | |
5 | |
4 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.