I have an ASP.Net application with the following code:
try
{
sql = new SqlProc("prcCustomerAgeSelect",
SqlProc.InParam("#DateFrom", SqlDbType.DateTime, 8, _OrderDateFrom),
SqlProc.InParam("#DateTo", SqlDbType.DateTime, 8, _OrderDateTo),
sql.Command.CommandTimeout = 1;
dt = sql.ExecuteTable();
}
catch (SqlException ex)
{
Filter.ErrorMessage = "Please narrow your search criteria.";
}
Note the line:
sql.Command.CommandTimeout = 1;
Which causes a SqlException to be thrown (for testing).
I would have thought that the catch block would catch this exception, but it doesn't. Instead, I get:
Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
[SqlException (0x80131904): Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.]
Why doesn't it catch it?? Am I using the wrong type? What am I missing here?
Thanks in advance!!
-Ev
It sounds like what you're seeing isn't a SqlException.
It's possible that SqlProc is itself catching SqlExceptions, extracting some information from them, then throwing new exceptions of a different type (embedding some of the original info in the new exception's message).
It looks like it may be a connection timeout, rather than a command timeout.
I would check to make sure that you can connect and run the query with a more sensible timeout value just to verify this.
Related
I am trying to catch if timeout error occurs in Oracle. After googling a lot i did not find any specific fix for it. I have done below
try{}
catch (OracleException ex)
{
if (ex.Number == 01013)
CatchException(ex);
}
But i am not sure if timeout exception number is 01013.
Yes the code is 01013. Please refer the Oracle docs:
Default is 0 seconds, which enforces no time limit.
When the specified timeout value expires before a command execution
finishes, the command attempts to cancel. If cancellation is
successful, an exception is thrown with the message of ORA-01013: user
requested cancel of current operation. If the command executed in time
without any errors, no exceptions are thrown.
In a situation where multiple OracleCommand objects use the same
connection, the timeout expiration on one of the OracleCommand objects
may terminate any of the executions on the single connection. To make
the timeout expiration of a OracleCommand cancel only its own command
execution, simply use one OracleCommand for each connection if that
OracleCommand sets the CommandTimeout property to a value greater than
0.
Please note that there are possibly two other error codes which will throw when the .CommandTimeout is exceeded. Those are ORA-00936 and ORA-00604. Found in the docs.
When the specified timeout value expires before a command execution finishes, the command attempts to cancel. If cancellation is successful, an exception is thrown with the message of ORA-01013: user requested cancel of current operation. Other possible exceptions thrown after a command timeout expiration occurs include ORA-00936 and ORA-00604. If the command executed in time without any errors, no exceptions are thrown.
So your code should be:
try
{
// Data Access
}
catch (OracleException ex)
{
if (ex.Number == 01013 || ex.Number == 00936 || ex.Number == 00604)
CatchException(ex);
}
I have a Console app that uses a parallel.foreach producing a number of working threads that performs some tasks such as
reading OS data through SNMP from a number of servers in our intranet and
writes these values to a SQL server DB.
When I ran the code within Visual Studio 2010 in either debug- or release mode the program executes without exceptions. When I deploy the program and run it outside VS I get an exception (.NET Runtime Exceptiopn).
Stack Trace:
Application: ServerMonitorSNMP.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: System.AggregateException Stack: at System.Threading.Tasks.Parallel.ForWorker[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](Int32, Int32, System.Threading.Tasks.ParallelOptions, System.Action`1,
...
at ServerMonitoringSNMP.Program.Main(System.String[])
The AggregateException details are:
System.UnhandledExceptionEventArgs
System.AggregateException: One or more errors occurred. ---> System.InvalidOperationException: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
...
(Inner Exception #0) System.InvalidOperationException: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
...
(Inner Exception #1) System.InvalidOperationException: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
...
(Inner Exception #2) System.InvalidOperationException: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
...
System.AggregateException: One or more errors occurred. ---> System.NullReferenceException: Object reference not set to an instance of an object.
at ServerMonitoringSNMP.Program.GetStorageValue(Dictionary`2 StorageQuery, Int32 diskOidIndex) in \Program.cs:line 896
This is an unhandled aggregate exception. You will need to catch this type of error, loop through its exceptions and log each one to figure out what is going on.
You are probably not breaking on these types of exceptions in your debug routine.
Turn on Break on All Exceptions (Debug, Exceptions) or (CTRL + ALT + E) and rerun the program.
This will show you the original exception when it was thrown in the first place.
Catch code:
catch (AggregateException e)
{
foreach (var ex in e.InnerExceptions)
{
//log here
}
}
The attached exception is too abstract. The best approach would be handle the TPL exception and log. Things shall be much clearer when you do so. Then you can updated the post with proper exception.
Eg:
try
{
YourSNMPTrapSenderMethod();
}
catch (AggregateException ae)
{
// This is where you can choose which exceptions to handle.
foreach (var ex in ae.InnerExceptions)
{
// log your exception. may be in temp directory
}
}
Or
try
{
YourSNMPTrapSenderMethod();
}
catch (AggregateException ex)
{
ex.Handle((x) =>
{
Log.Write(x);
return true;
});
}
static void YourSNMPTrapSenderMethod()
{
var exceptions = new ConcurrentQueue<Exception>();
Parallel.ForEach(data, d =>
{
try
{
//do your operations
}
catch (Exception e) { exceptions.Enqueue(e); }
});
if (exceptions.Count > 0) throw new AggregateException(exceptions);
}
Just wondering if anyone knows how to display the status of a DB connection on a page.
I would like to know if there is a good connection, or if it is down. In this case I would also display the reason.
While working with database with asp.net, you connection shouldn't be open all the time. Keeping in this mind you dont have to (and shouldnt) display connection status of database all the time. What you should do is while performing queries with ado.net or another OR/M just capture SqlExceptions and provide meaningfull errors to your user.
From msdn article :
try {
// code here
}
catch (SqlException odbcEx) {
// Handle more specific SqlException exception here.
}
catch (Exception ex) {
// Handle generic ones here.
}
Just capture the db exception, cause it will fire an exception/error once there is no connection.
and if there is a connection, you would know
There could be many ways to check for connection status, You may use ASP.Net Timer to periodically check for the connection, (remember that each timer interval causes a postback to the server and causes network traffic ), See Walkthrough: Using the ASP.NET Timer Control with Multiple UpdatePanel Controls
In the Timer_Tick event, you may check for the connection and post a message in label. Something on the following lines...
protected void Timer1_Tick(object sender, EventArgs e)
{
try
{
using (SqlConnection sqlConn =
new SqlConnection("YourConnectionString"))
{
sqlConn.Open();
Label1.Text = "Database Available";
}
}
catch (Exception ex)
{
Label1.Text = "Database Un-Available, " + "Possible Reason:"+ ex.Message;
}
}
Its not a good practice to catch generic exception (Exception) , you may catch SQLException and then have another block to handle generic exception.
Ideally, it is not really a good practice to tell users about database. Any database error should be logged and replaced with a more user friendly error message.
If you still need to display connection state on the screen, you can handle the StateChange event for SQLConnection and display appropriate message.
Update: I would suggest that you just log the errors and have a program to send you emails with failures or manually look into the system rather than users telling you that your database is down.
I one of my c# application, i have written sql connection code as following
try
{
myConnection = new SqlConnection(m_resourceDB.GetResourceString(nSiteID, ApplicationID.XClaim,(short)nResID ) );
myConnection.open();
}
I want to handle unkown issue of sqlserver like database down, time out.
For this i though to introduce for loop 3 times with 3 minute sleep between loop and if at all problem is there then i will exit from loop
I don't know my though is right or not? I want some expert advice on this? Any example?
I would say simply: the code that talks to connections etc should not be doing a sleep/retry, unless that code is already asynchronous. If the top-level calling code wants to catch an exception and set up a timer (not a sleep) and retry, then fine - but what you want to avoid is things like:
var data = dal.GetInfo();
suddenly taking 3 minutes. You might get away with it if it is an async/callback, and you have clearly advertised that this method may take minutes to execute. But even that feels like a stretch. And if you are up at the application logic, why not just catch the exception the first time, tell the user, and let the user click the button again at some point in the future?
If you are running a service with no user interface, then by all means, keep on looping until things start working, but at least log the errors to the EventLog while you're at it, so that the server admin can figure out when and why things go wrong.
For a client application, I would no suggest that you make the user wait 9 minutes before telling them things are not working like they should. Try to connect, assess the error condition, and let the user know what is going wrong so that they can take it further.
If you are using the SqlException class you can check the Exception Class and decide based on that what is going wrong, for example:
switch (sqlEx.Class)
{
case 20:
//server not found
case 11:
//database not found
All the classes have the SQL Server message on them, it is a matter of testing the different conditions.
It really depends on how you want your application to behave.
If your database access is dealt with on the same thread as your UI then whilst you are attempting to connect to a database it will become unresponsive.
The default time period for a connection timeout is already pretty long and so running it in a for loop 3 times would triple that and leave you with frustrated users.
In my opinion unless your specifically attempting to hide connection issues from the user, it is by far better to report back that a connection attempt has failed and ask the user if they wish to retry. Then having a count on the number of times that you'll allow a reconnection attempt before informing the user that they can't continue or putting the application into an "out of service" state.
I want to handle unkown issue of sqlserver like database down, time out.
Try to surround connection operation with using statement to capture connection related problems .
using( sqlcon = new SqlConnection(constr))
{}
Use the Try/Catch Statement for capturing the exception:
try
{
con.Open();
try
{
//Execute Queries
// ....
}
catch
{
// command related or other exception
}
finally
{
con.Close();
}
}
catch
{
// connection error
}
To prevent Exception of such type check these:
Troubleshooting Timeout SqlExceptions
you can set the CommandTimeout to some value on a SqlCommand:
objCmd.CommandTimeout = 600
You can catch the SqlException.
SqlException.Class
Gets the severity level of the error returned from the .NET Framework Data Provider for SQL Server.
SqlException.Errors
Gets a collection of one or more SqlError objects that give detailed information about exceptions generated by the .NET Framework Data Provider for SQL Server.
SqlCommand cmd = new SqlCommand();
cmd.Connection = new SqlConnection("CONNECTION_STRING");
cmd.CommandText = "SELECT * FROM ....";
// cmd.CommandType = System.Data.CommandType.Text;
try
{
cmd.Connection.Open();
try
{
SqlDataReader reader = cmd.ExecuteReader();
// ....
}
finally
{
cmd.Connection.Close();
}
}
catch (SqlException ex)
{
// ex.Class contains the ErrorCode, depends on your dataprovider
foreach (SqlError error in ex.Errors)
{
// error.LineNumber
// error.Message
}
}
The best way would be to putt it in a try catch statement and display the error in a better format, If it fails for 1 time, trying it continue sly 3 times will not change anything untill and unless you dc and send request again, In a separate in separate packed as a new request.
use try this.
try
{
Executing code.
}
catch (Exception err)
{
Display["ErrorMsg"] = err.Message.ToString() + "|" + err.GetBaseException() + "|" + Request.Url.ToString();
}
Good Luck.
Suggestions on resolving this? I keep coming up with "missing" line numbers when consulting the google machine and that isn't the issue we are having. We have a line number but it doesn't point to anything but a closing brace.
Could this be because it is a timeout? It seems strange that it consistently gives up at the very end of the method, and the same method no less. The time outs are not necessarily frequent and the application (win forms calling asmx web service) does timeout in other places at times.
Edit: Code and Stack trace.
public DataSet GetData(...)
{
// About 18 try/catch blocks loading tables in dataset, all similar to below
try
{
// Create Table Adapter
// Fill Table
}
catch (Exception ex)
{
LogError(ex, System.Reflection.MethodBase.GetCurrentMethod(), null);
throw ex;
}
} //Line 479
System.Web.Services.Protocols.SoapException:
System.Web.Services.Protocols.SoapException:
Server was unable to process request.
---> System.Data.SqlClient.SqlException:
Timeout expired. The timeout period
elapsed prior to completion of the
operation or the server is not
responding. at
MonitoringDataService.AddAllData(DataSet
Data, DateTime LastSync, String
PrevAreas, String NewAreas, DateTime
PrevStartDate, DateTime PrevEndDate,
DateTime NewStartDate, DateTime
NewEndDate, Int32 CurrentUser, Boolean
IsInGroup) in
MonitoringDataService.cs:line 479
Worth noting that this is the inner exception.
Likely causes:
The code that is running is different from the source you are debugging from. This is the most likely cause.
Line could be the line after a throw new exception(...)
More than likely it's not really erroring on the end brace, but the line before it.