I have a case where on a pretty regular select the call to SqlDataReader.Close() takes 10+ seconds to return. The only thing unusual is the select returns 20 rows but in this case none of the rows are read.
DbDataReader reader = (DbDataReader) cmd.ExecuteReader(CommandBehavior.Default);
reader.MoveNext();
var row = de.Current;
// lots of other code that does not touch this.
reader.Close();
Why does it take so long? And more important, what can I do to make it fast?
I couldn't find out what/why this is occurring. So on the call to close my object, I create a worker thread and have that close the data reader and connection. I then return immediately so the user sees no delay. Works fine.
Update: As per SqlDataReader.Close() it can be reduced by calling the Cancel method of the associated SqlCommand object before calling the Close method. h/t Lingaraj Mishra
I'm facing a very buggy issue, in ASP.NET application after viewing the same report many times simultaneously I got this exception:
The maximum report processing jobs limit configured by your system
administrator has been reached.
Wait I know there are tons of solutions out there but all of them are not working with me.
I put ReportDocument.Close(); ReportDocument.Dispose(); in CrystalReportViewer_Unload event, and still throw the exception.
Private Sub CrystalReportViewer1_Unload(ByVal sender As Object, ByVal e As System.EventArgs) Handles CrystalReportViewer1.Unload
reportFile.Close()
reportFile.Dispose()
GC.Collect()
End Sub
I edit the PrintJobLimit registry in HKEY_LOCAL_MACHINE\SOFTWARE\SAP BusinessObjects\Crystal Reports for .NET Framework 4.0\Report Application Server\InprocServer and HKEY_LOCAL_MACHINE\SOFTWARE\SAP BusinessObjects\Crystal Reports for .NET Framework 4.0\Report Application Server\Server to -1 even to 9999, and still throw the exception.
Here is the code snippet where I call my report:
Table_Infos = New TableLogOnInfos()
Table_Info = New TableLogOnInfo()
Con_Info = New ConnectionInfo()
With Con_Info
.ServerName = ConfigurationManager.AppSettings("server_name")
.DatabaseName = ConfigurationManager.AppSettings("DB")
.UserID = user_name
.Password = pass_word
.Type = ConnectionInfoType.SQL
.IntegratedSecurity = False
End With
Table_Info.ConnectionInfo = Con_Info
If Session("recpt_lang") = "Arabic" Then
reportFile.Load(Server.MapPath("/Reports/") & "collectrecpt_new_ar.rpt")
ElseIf Session("recpt_lang") = "English" Then
reportFile.Load(Server.MapPath("/Reports/") & "collectrecpt_new.rpt")
End If
For Each mytable In reportFile.Database.Tables
mytable.ApplyLogOnInfo(Table_Info)
Next
CrystalReportViewer1.ReportSource = reportFile
CrystalReportViewer1.SelectionFormula = Session("SelectionForumla")
CrystalReportViewer1 = Nothing
You have to Dispose your report instance after all.
If you Dispose the report after showing it, you will never see the error "The maximum report processing jobs limit configured by your system administrator has been reached" again.
Dim report1 As rptBill = clsBill.GetReport(billNumber)
rpt.Print()
'Cleanup the report after that!
rpt.Close()
rpt.Dispose()
I would recommend moving your close/dispose/gc.collect code outside of that unload process. In other words:
Load report
Assign to Viewer Control
Show Report in Viewer Control
Close Viewer Control and Unload (completely)
Then close/dispose/gc.collect outside of any viewer control code
My guess is the viewer control is not completely closed when the report is being cleaned up.
Crystal is a very memory intensive process and very finicky.
Crystal Report document implements IDisposable interface. So all you have to do is to enclose the report's instance with using statement. It will be automatically closed and disposed once the using statement is completed. You can write something like that:
using(var report = GetInvoiceReport())
{
// your logic here
}
or (depends on your context):
using(var report = new ReportDocument())
{
// your logic here
}
Greetings I am too late to have answer on it,
all reply are working and i have seen but in case still you are facing same problem and error then please once go in to TEMP folder under "windows" directory and delete all instances of crystal report.
I am saying this because all above option will work but you are still in the maximum reach so first of all delete all instance then apply all the above suggestion.
thanks
Make sure you are using PUSH model to display your reports. Next you have to make one change in your Server's registry: Follow the path:
"HKEY_LOCAL_MACHINE\SOFTWARE\SAP BusinessObjects\Crystal Reports for .NET Framework 4.0\Report Application Server\InprocServer"
and you will see an item " PrintJobLimit" and you will see that its default value is 75. that means the server can only handle 75 reports at a time.
Dont worry about that and just modify the value to -1
Make sure IIS user have sufficient permission to delete files present in "c:/windows/temp" folder.
I face the same issue once I provide write permission to that folder then it solved my issue.Also make sure dispose that object after generating the file
I was working on local report server. I have hosted my web application in other pc. When I got such error I just did IISRESET and working fine now.
Try this, this could help you.
You have to Dispose your report instance after all. If you Dispose the report after showing it, you will never see the error:
The maximum report processing jobs limit configured by your system administrator has been reached
Code:
Dim report1 As rptBill = clsBill.GetReport(billNumber)
rpt.Print()
'Cleanup the report after that!
rpt.Close()
rpt.Dispose()
In my case, the report had 4 subreports...
What solved for me was changing the value of "PrintJobLimit", from 75 to 500, in the following Regedit paths:
\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\SAP BusinessObjects\Crystal Reports for .NET Framework 4.0\Report Application Server\InprocServer
\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\SAP BusinessObjects\Crystal Reports for .NET Framework 4.0\Report Application Server\Server
I know this thread is older, but if you configure the app pool setting "Recycling..." to recycle at, say, 180 minutes instead of 1740 minutes (the default), this might free up the needed resources.
Use These methods when unload the page
ReportDocument crystalReport;
protected void Page_Unload(object sender, EventArgs e)
{
if (crystalReport != null)
{
crystalReport.Close();
crystalReport.Dispose();
}
}
OR
protected void Page_Unload(object sender, EventArgs e)
{
if (crystalReport != null)
{
crystalReport.Close();
crystalReport.Clone();
crystalReport.Dispose();
crystalReport = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
I ended up using GC.WaitForPendingFinalizers in addition to the GC.Collect, close and dispose. I believe my web page was perhaps unloading and stopping thread processing prematurely before the garbage was properly processed (really?)
This is on Server 2012, SQL 2012, CR 13.0.2000.0
Here's my code:
#Region "Cleanup"
Private Sub crCleanup(Optional blnForce As Boolean = False)
Try
' Crystal(code Is Not managed, i.e.it) 's COM interop => you have to manually
' release any objects instantiated. Make sure you set the ref to nothing and
' also call the dispose method if it has one.
' under some conditions, we don't want to destroy the ReportDocument (e.g. report page-to-page navigation)
If blnForce OrElse Me.blnPageHasFatalError OrElse (Not Me.CrystalUseCache) Then ' do not release when using cache! (unless forced)
If Not crReportDocument Is Nothing Then Me.crReportDocument.Close()
If Not crReportDocument Is Nothing Then Me.crReportDocument.Dispose()
If Not thisWebAppUser Is Nothing Then Me.thisWebAppUser.Dispose()
Me.thisWebAppUser.ClearReportCache() ' we are using HttpContext.Current.Cache.Item instead of sessions to save CR document
End If
' the rest of the items, we'll always want to clean up
If Not crParameterFieldDefinitions Is Nothing Then crParameterFieldDefinitions.Dispose()
If Not crParameterFieldDefinition Is Nothing Then crParameterFieldDefinition.Dispose()
crParameterFields = Nothing
crParameterField = Nothing
crParameterFieldName = Nothing
crParameterValues = Nothing
crParameterDiscreteValue = Nothing
crParameterDefaultValue = Nothing
crParameterRangeValue = Nothing
'
If Not crSections Is Nothing Then crSections.Dispose()
If Not crSection Is Nothing Then crSection.Dispose()
If Not crReportObjects Is Nothing Then crReportObjects.Dispose()
If Not crReportObject Is Nothing Then crReportObject.Dispose()
If Not crSubreportObject Is Nothing Then crSubreportObject.Dispose()
If Not crDatabase Is Nothing Then crDatabase.Dispose()
If Not crTables Is Nothing Then crTables.Dispose()
If Not crTable Is Nothing Then crTable.Dispose()
crLogOnInfo = Nothing
crConnInfo = Nothing
crDiskFileDestinationOptions = Nothing
ConnParam = Nothing
If Not subRepDoc Is Nothing Then subRepDoc.Dispose()
Catch ex As Exception
Me.thisWebAppUser.SendSysAdminMessage("Failed CR cleanup", ex.ToString)
End Try
' yes, use of the GC.Collect (and even more the GC.WaitForPendingFinalizers) is highly controversial
'
' the reality is that rendering crystal reports is rather slow compared to most web operations
' so it is expected that waiting for GC will have relatively little performance impact
' and will in fact, help tremendously with memory management.
'
' try setting these values to 1 and confirm for yourself by instantiating multiple crDocuments in different browsers if you don't believe it:
'
' HKEY_LOCAL_MACHINE\SOFTWARE\SAP BusinessObjects\Crystal Reports for .NET Framework 4.0\Report Application Server\InprocServer
' HKEY_LOCAL_MACHINE\SOFTWARE\SAP BusinessObjects\Crystal Reports for .NET Framework 4.0\Report Application Server\Server
'
' or google this error: The maximum report processing jobs limit configured by your system administrator has been reached
'
' I believe the problem is that on very fast servers, the page unloads and stops processing code to properly cleanup the Crystal Report objects
'
' This is done in 3 places:
' Report Viewer (Page_Unload and CrystalReportViewer1_Unload) rendering a report will of course always using a processing job
' Report Parameter Selector (Page_Unload) loading a crDocument without rendering a report still counts towards CR processing job limit.
' Custom Control crReportParameterSelectionTable (Public Overrides Sub dispose())
GC.Collect()
GC.WaitForPendingFinalizers()
End Sub
'***********************************************************************************************************************************
'
'***********************************************************************************************************************************
Private Sub Page_Unload(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Unload
'If Me.IsCallback Then Exit Sub ' the menutree causes callbacks, but we are not interested
crCleanup()
' response object not available here, so cannot redirect (such as in the case of XLS opeing in a separate window)
' if for some crazy reason there is STILL a crReportDocument, set it to nothing
' If Not crReportDocument Is Nothing Then Me.crReportDocument = Nothing
' Me.CrystalReportViewer1 = Nothing
End Sub
Private Sub CrystalReportViewer1_Unload(ByVal sender As Object, ByVal e As System.EventArgs) Handles CrystalReportViewer1.Unload
'If Me.IsCallback Then Exit Sub ' the menutree causes callbacks, but we are not interested
crCleanup()
End Sub
End Region
ScopedDBConnection's constructor gets a connection from pool(if can't it will create a new one) and save it as a private member variable.Its get method returns a pointer of DBClientBase,I thinks client code don't need to delete this pointer because the done method will return it back to the pool. Here is my code,am I right.
ScopedDbConnection con(...);
DBClientBase* session = con.get();
//do something using session
...
//
con.done();// ignore session because done will return it back to connection pool
You can find a number of good ScopedDbConnection examples in the MongoDB github. Here's a file that shows some basic usage of that class:
https://github.com/mongodb/mongo/blob/master/src/mongo/client/model.cpp
Check out lines 24-46 (Model::load).
I am reviewing an application that uses Microsoft Application Blocks for Data Access to interact with the database. The application calls a function and pass a query into it. The function creates a DataReader object using Data Access application blocks (for the given query) and returns the DataReader to the caller.
The application closes DataReader object when it is done. The question I have is, whether closing the DataReader object automatically closes the underlying connection object or not. It is not clear to me whether the Data Access Application Block opens the command object with the "CommandBehavior.CloseConnection" flag.
Questions:
When the Close() method is called on a DataReader object, does it also close the underlying connection object (the DataReader is created using Microsoft Application Blocks - Database.ExecuteReader() method
If not, what is the recommended method to ensure that the connection is freed after we are done with the data reader?
Thanks in advance
http://msdn.microsoft.com/en-us/library/system.data.commandbehavior.aspx
CloseConnection: When the command is executed, the associated Connection object is closed when the associated DataReader object is closed.
It is always a good practice to close and dispose of your objects manually. The GC will eventually collect them, but you don't know when, and when dealing with a database you don't want open connections hanging around eating up resources.
So to answer your questions:
1) Yes, DataReader.Close() will close the connection. This is relevant when dealing with any connected object.
As soon as you close the reader, the connection it was using is then
closed automatically as well. Because Readers are connected objects
(the need an open connection to function correctly), you can't close
the Connection before you are done with the reader.
http://p2p.wrox.com/book-beginning-asp-net-1-0/11037-sqldatareader-close-connection.html
also look at: http://msdn.microsoft.com/en-us/magazine/cc188705.aspx
2) I would recommend putting the connection in a using statement:
**these are done using regular SQLClient objects, but they will work with all objects that inherit from the System.Data.Common.DbCommant, System.Data.Common.DbConnection etc. classes.
using(SqlConnection con = new SqlConnection(....))
{
//blah blah blah
con.close();
}
Dispose will be called at the end of the using, which will call close, but I still like to implicitly call it.
or, you can put it in a try/catch statement:
SQLConnection con = new SqlConnection(...);
try
{
con.open();
}
catch(Exception ex)
{
}
finally
{
//depending on the version of .NET you might want to do:
//if(con.State != System.Data.ConnectionState.Closed)
// con.Close();
con.close();
}
Miguel Angel Utiel's answer is right, if you use "CommandBehavior.CloseConnection", the connection will close after reader closed. just like this:
OracleDataReader odr = oc.ExecuteReader(CommandBehavior.CloseConnection);
odr.Close();
if (oc.Connection.State == System.Data.ConnectionState.Closed) {
System.Diagnostics.Debug.WriteLine("connection is closed");
}
if your ExecuteReader() with no parameter,just like
OracleDataReader odr = oc.ExecuteReader();
odr.Close();
if (oc.Connection.State != System.Data.ConnectionState.Closed) {
System.Diagnostics.Debug.WriteLine("connection is openning");
}
read:http://msdn.microsoft.com/en-us/library/system.data.commandbehavior.aspx
I'm in the process of writing a query manager for a WinForms application that, among other things, needs to be able to deliver real-time search results to the user as they're entering a query (think Google's live results, though obviously in a thick client environment rather than the web). Since the results need to start arriving as the user types, the search will get more and more specific, so I'd like to be able to cancel a query if it's still executing while the user has entered more specific information (since the results would simply be discarded, anyway).
If this were ordinary ADO.NET, I could obviously just use the DbCommand.Cancel function and be done with it, but we're using EF4 for our data access and there doesn't appear to be an obvious way to cancel a query. Additionally, opening System.Data.Entity in Reflector and looking at EntityCommand.Cancel shows a discouragingly empty method body, despite the docs claiming that calling this would pass it on to the provider command's corresponding Cancel function.
I have considered simply letting the existing query run and spinning up a new context to execute the new search (and just disposing of the existing query once it finishes), but I don't like the idea of a single client having a multitude of open database connections running parallel queries when I'm only interested in the results of the most recent one.
All of this is leading me to believe that there's simply no way to cancel an EF query once it's been dispatched to the database, but I'm hoping that someone here might be able to point out something I've overlooked.
TL/DR Version: Is it possible to cancel an EF4 query that's currently executing?
Looks like you have found some bug in EF but when you report it to MS it will be considered as bug in documentation. Anyway I don't like the idea of interacting directly with EntityCommand. Here is my example how to kill current query:
var thread = new Thread((param) =>
{
var currentString = param as string;
if (currentString == null)
{
// TODO OMG exception
throw new Exception();
}
AdventureWorks2008R2Entities entities = null;
try // Don't use using because it can cause race condition
{
entities = new AdventureWorks2008R2Entities();
ObjectQuery<Person> query = entities.People
.Include("Password")
.Include("PersonPhone")
.Include("EmailAddress")
.Include("BusinessEntity")
.Include("BusinessEntityContact");
// Improves performance of readonly query where
// objects do not have to be tracked by context
// Edit: But it doesn't work for this query because of includes
// query.MergeOption = MergeOption.NoTracking;
foreach (var record in query
.Where(p => p.LastName.StartsWith(currentString)))
{
// TODO fill some buffer and invoke UI update
}
}
finally
{
if (entities != null)
{
entities.Dispose();
}
}
});
thread.Start("P");
// Just for test
Thread.Sleep(500);
thread.Abort();
It is result of my playing with if after 30 minutes so it is probably not something which should be considered as final solution. I'm posting it to at least get some feedback with possible problems caused by this solution. Main points are:
Context is handled inside the thread
Result is not tracked by context
If you kill the thread query is terminated and context is disposed (connection released)
If you kill the thread before you start a new thread you should use still one connection.
I checked that query is started and terminated in SQL profiler.
Edit:
Btw. another approach to simply stop current query is inside enumeration:
public IEnumerable<T> ExecuteQuery<T>(IQueryable<T> query)
{
foreach (T record in query)
{
// Handle stop condition somehow
if (ShouldStop())
{
// Once you close enumerator, query is terminated
yield break;
}
yield return record;
}
}