This question already has answers here:
try/catch + using, right syntax
(9 answers)
Closed 9 years ago.
I've been implementing TRY-CATCH relative to USING like the following example:
private void someDatabaseMethod(string userName) {
try {
using(var conn = new SqlConnection(connString))
using(var comm = new SqlCommand()) {
comm.Connection = conn;
comm.CommandType = CommandType.Text;
comm.CommandText = string.Concat(#"SELECT UserID FROM xxx WHERE UserName = '", userName,#"'");
conn.Open();
object x = comm.ExecuteScalar();
UserID = (x==null)? 0: (int)x;
}
} catch(Exception) {
throw;
}
}
I've just seen this MSDN EXAMPLE which seems to point towards the TRY-CATCH being within the USING. So my example would look like the following:
private void someDatabaseMethod(string userName) {
using(var conn = new SqlConnection(connString))
using(var comm = new SqlCommand()) {
comm.Connection = conn;
comm.CommandType = CommandType.Text;
comm.CommandText = string.Concat(#"SELECT UserID FROM xxx WHERE UserName = '", userName,#"'");
try {
conn.Open();
object x = comm.ExecuteScalar();
UserID = (x==null)? 0: (int)x;
} catch(Exception) {
throw;
}
}
}
Is this a more efficient layout? If so, why?
EXTRA ADDITIONAL NOTE
The reason for the TRY-CATCH is to re-throw the exception so that I bubble it up to the next level - so I'd like to have a CATCH somewhere in the code.
It depends on your goals. If you want to do something with command or connection in catch block, then it should be within using.
TRY-CATCH I use in using only if I want to LOG Exception or it I have transaction - to rollback it in except block.
using is translated by compiler in TRY-FINALLY - you can check it with IL Disassembler (ildasm.exe) or reflector to release your disposable resources.
so that
using is equivalent to :
try
{
//do job
}
finally
{
Resource.Dispose()
}
If you just throw the catched exception, the try-catch block isn't necessary at all. The using will dispose the conenction and command properly.
Second one is more efficient. For first one; you can not access connection object from catch block, and can not close it. Also if you was using a transaction over this connection, you could not rollback the transaction when any error occurs...
Don't catch exceptions you cannot handle at this place.
catch{throw;} is of no use except adding complexity
catch and handle exceptions as near at the exception source as you are able to handle them
Read extensive discussion here
Related
Im making a system which should be running 24/7, with timers to control it. There are many calls to the database, and at some point, two methods are trying to open a connection, and one of them will fail. I've tried to make a retry method, so my methods would succeed. With the help from Michael S. Scherotter and Steven Sudit's methods in Better way to write retry logic without goto, does my method look like this:
int MaxRetries = 3;
Product pro = new Product();
SqlConnection myCon = DBcon.getInstance().conn();
string barcod = barcode;
string query = string.Format("SELECT * FROM Product WHERE Barcode = #barcode");
for (int tries = MaxRetries; tries >= 0; tries--) //<-- 'tries' at the end, are unreachable?.
{
try
{
myCon.Open();
SqlCommand com = new SqlCommand(query, myCon);
com.Parameters.AddWithValue("#barcode", barcode);
SqlDataReader dr = com.ExecuteReader();
if (dr.Read())
{
pro.Barcode = dr.GetString(0);
pro.Name = dr.GetString(1);
}
break;
}
catch (Exception ex)
{
if (tries == 0)
Console.WriteLine("Exception: "+ex);
throw;
}
}
myCon.Close();
return pro;
When running the code, the program stops at the "for(.....)", and the exception: The connection was not closed. The connection's current state is open... This problem was the reason why I'm trying to make this method! If anyone knows how to resovle this problem, please write. Thanks
You do
myCon.Open();
inside the for loop, but
myCon = DBcon.getInstance().conn();
outside of it. This way you try to open the same connection multiple times. If you want to protect against loss of DB connection you need to put both inside teh loop
You should move the call to myCon.Open outside the for statement or wrap myCon.Open() checking the connection state before re-opening the connection:
if (myCon.State != ConnectionState.Open)
{
myCon.Open();
}
Edited for new information
How about using Transactions to preserve data integrity, getting on-the-fly connections for multiple access and wrapping them in Using statements to ensure connections are closed? eg
Using (SqlConnection myCon = new SqlConnection('ConnectionString'))
{
myCon.Open();
var transaction = myCon.BeginTransaction();
try
{
// ... do some DB stuff - build your command with SqlCommand but use your transaction and your connection
var sqlCommand = new SqlCommand(CommandString, myCon, transaction);
sqlCommand.Parameters.Add(new Parameter()); // Build up your params
sqlCommand.ExecuteNonReader(); // Or whatever type of execution is best
transaction.Commit(); // Yayy!
}
catch (Exception ex)
{
transaction.RollBack(); // D'oh!
// ... Some logging
}
myCon.Close();
}
This way even if you forget to Close the connection, it will still be done implicitly when the connection gets to the end of its Using statement.
Have you tried adding
myCon.Close();
Into a Finally block. It looks like it is never being hit if you have an exception. I would highly recommend that you wrap the connection, command object etc in Using statements. This will ensure they are disposed of properly and the connection is closed.
I have the following code
try
{
using (var connection = new SqlConnection(Utils.ConnectionString))
{
connection.Open();
using (var cmd = new SqlCommand("StoredProcedure", connection))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
var sqlParam = new SqlParameter("id_document", idDocument);
cmd.Parameters.Add(sqlParam);
int result = cmd.ExecuteNonQuery();
if (result != -1)
return "something";
//do something here
return "something else";
}
}
//do something
}
catch (SqlException ex)
{
return "something AKA didn't work";
}
The question is: Does var connection still get closed if an unexpected error happens between the using brackets ({ })?
The problem is that most of my calls to stored procedures are made this way, and recently I have been getting this error:
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.
The other way I access the DB is through nHibernate.
using Statement (C# Reference)
The using statement ensures that Dispose is called even if an
exception occurs while you are calling methods on the object. You can
achieve the same result by putting the object inside a try block and
then calling Dispose in a finally block; in fact, this is how the
using statement is translated by the compiler. The code example
earlier expands to the following code at compile time (note the extra
curly braces to create the limited scope for the object):
Yes, if it gets into the body of the using statement, it will be disposed at the end... whether you reached the end of the block normally, exited via a return statement, or an exception was thrown. Basically the using statement is equivalent to a try/finally block.
Is that the only place you acquire a connection? Has your stored procedure deadlocked somewhere, perhaps, leaving lots of connections genuinely "busy" as far as the client code is concerned?
In terms of your connection pool running out of available connections, if you are in a distributed environment and using many applications to access SQL Server but they all use the same connection string, then they will all be using the same pool on the server. To get around this you can change the connection string for each application by setting the connection WorkstationID to the Environment.MachineName. This will make the server see each connection as different and provide a pool to each machine instead of sharing the pool.
In the below example we even pass in a token to allow an application on the same machine to have multiple pools.
Example:
private string GetConnectionStringWithWorkStationId(string connectionString, string connectionPoolToken)
{
if (string.IsNullOrEmpty(machineName)) machineName = Environment.MachineName;
SqlConnectionStringBuilder cnbdlr;
try
{
cnbdlr = new SqlConnectionStringBuilder(connectionString);
}
catch
{
throw new ArgumentException("connection string was an invalid format");
}
cnbdlr.WorkstationID = machineName + connectionPoolToken;
return cnbdlr.ConnectionString;
}
Replace your above code.. by this.. and check again..
try
{
using (var connection = new SqlConnection(Utils.ConnectionString))
{
connection.Open();
using (var cmd = new SqlCommand("StoredProcedure", connection))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
var sqlParam = new SqlParameter("id_document", idDocument);
cmd.Parameters.Add(sqlParam);
int result = cmd.ExecuteNonQuery();
if (result != -1)
return "something";
//do something here
return "something else";
}
connection.Close();
connection.Dispose();
}
//do something
}
catch (SqlException ex)
{
return "something AKA didn't work";
}
Here's a reference:
http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx
What I know is that if you use an object within the using {} clause, that object inherits the IDisposable interface (i.e. SqlConnection inherits DbConnection, and DbConnection inherits IDisposable), which means if you get an exception, any object will be closed and disposed properly.
Ive been doing some research today on when an how to use the "using" statement to dispose of my sql objects.
However I'm still confused about when and how to catch unforseen errors. I have a simple method here and would appreciate any input on wheter its correct or I'm doing something wrong?
private BindingList<My_Object> Search(int ID)
{
string strSelectStatement =
"SELECT 'coloumns' " +
"FROM 'table' " +
"WHERE ID = #ID;";
DataTable dt = new DataTable();
try
{
using (SqlConnection sqlConn = new SqlConnection(m_SQLConnectionString))
{
using (SqlCommand cmd = new SqlCommand(strSelectStatement, sqlConn))
{
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = ID;
using (SqlDataAdapter adpt = new SqlDataAdapter(cmd))
{
adpt.Fill(dt);
}
}
}
My_Object myObject;
BindingList<My_Object> myObjectList = new BindingList<My_Object>();
foreach (DataRow row in dt.Rows)
{
myObject = new My_Object();
//Fill/set myObject properties and add to myObject list
}
return myObjectList;
}
catch (Exception)
{
//throw the the exception with its stack trace up to the main call
throw;
}
}
So what my catch here would do is catch an error if anything went wrong when running adapter.Fill, or while building myObject/list for example.
Thanks
In C# . The using statement defines the scope of an item to be disposed. This can be called for any object which implements the IDisposable interface.
http://msdn.microsoft.com/en-us/library/system.idisposable.aspx
So if you had to not use using blocks you would call the dispose method on the class to release/clean up resources created by the object.
When calling a class that implements the IDisposable interface, the try/finally pattern make sure that unmanaged resources are disposed of even if an exception interrupts your application.
If an exception is thrown in the case of a using statement the dispose will still be called. You can also stack using statements
using (SqlConnection sqlConn = new SqlConnection(m_SQLConnectionString))
using (SqlCommand cmd = new SqlCommand(strSelectStatement, sqlConn))
{
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = ID;
using (SqlDataAdapter adpt = new SqlDataAdapter(cmd))
{
adpt.Fill(dt);
}
}
with regards to exception handling. It is not wise to catch all exceptions try to catch the specific exceptions thrown by the class or method. You can view exception details on msdn so SQLConnection : http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.open.aspx
InvalidOperationException
Cannot open a connection without specifying a data source or server.
or
The connection is already open.
SqlException
A connection-level error occurred while opening the connection. If the Number property contains the value 18487 or 18488, this indicates that the specified password has expired or must be reset. See the ChangePassword method for more information.
So these are the exceptions you should cater for. Hope that helps!
Don't catch 'unforeseen' errors, since there's nothing you can do if truly unforeseen.
Unless of course you are wishing to handle these errors in some way, say, to log messages - but the system does that for you - then they are no longer 'unforeseen', since you're expecting them.
As for the code posted, there are problems. Firstly, the try / catch could be said to be trying too much, and given that you have usings in there, that is pointless (if exceptions aren't going to be handled.) It also catches a generic exception, which is highly discouraged; catches should be formulated to filter those that you can handle, and in appropriate order. To catch just to throw is also pointless.
Don't catch exceptions if you can do nothing about it. If you catch them is in order to clean up the unmanaged ressources or for logging purposes.
You might have a look on MSDN "Best Practices for Handling Exceptions" http://msdn.microsoft.com/en-us/library/seyhszts.aspx
You don't need the try..catch {throw}. This is the same as not having a try..catch block at all.
If you want to log the error of display a friendly message, then put the code in the catch { }.
The Dispose will still be called on the SqlConnection, even if the code crashes.
You can catch multiple exceptions at the end of your try statement. This means you can catch each different type of error that could occur i.e. InvalidOperationException / SqlException. MSDN Explains here:
http://msdn.microsoft.com/en-us/library/ms173162(v=vs.80).aspx
Since you have enclosed your whole code in try/Catch it will catch all errors raised within try/catch code block.
But don't follow this apprach only catch those errors specifically which you want to handle or log.
this is recommended because catching error is an overhead.
If I use "using" construct, I know that the object gets automatically disposed. What happens if a statement inside an "using" construct raises an exception. Is the "using" object still disposed? If so, when?
A using block is converted - by the compiler - to this:
DisposableType yourObj = new DisposableType();
try
{
//contents of using block
}
finally
{
((IDisposable)yourObj).Dispose();
}
By putting the Dispose() call in the finally block, it ensures Dispose is always called - unless of course the exception occurs at the instantiation site, since that happens outside the try.
It is important to remember that using is not a special kind of operator or construct - it's just something the compiler replaces with something else that's slightly more obtuse.
This article explains it nicely.
Internally, this bad boy generates a try / finally around the object being allocated and calls Dispose() for you. It saves you the hassle of manually creating the try / finally block and calling Dispose().
Actually Using block is Equivalent to try - finally block, Which ensures that finally will always execute e.g.
using (SqlConnection con = new SqlConnection(ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("Command", con))
{
con.Open();
cmd.ExecuteNonQuery();
}
}
Equals to
SqlConnection con = null;
SqlCommand cmd = null;
try
{
con = new SqlConnection(ConnectionString);
cmd = new SqlCommand("Command", con);
con.Open();
cmd.ExecuteNonQuery();
}
finally
{
if (null != cmd);
cmd.Dispose();
if (null != con)
con.Dispose();
}
I'm going through some old C#.NET code in an ASP.NET application making sure that all SqlConnections are wrapped in using blocks.
This piece of code used to open cn and da and close and dispose them in both the catch block and the end of the method. I added the usings and can't figure out for certain if the using blocks still handle disposing of the connection if an exception is thrown in the try and caught in the catch. This question seems to suggest that it does.
using (SqlConnection cn = new SqlConnection(Global.sDSN))
{
using (SqlDataAdapter da = new SqlDataAdapter())
{
// do some stuff
try
{
// do stuff that might throw exceptions
}
catch (catch (System.Exception e)
{
//return something here
// can I ditch these because the using's handle it?
da.Dispose();
cn.Close();
cn.Dispose();
return msg;
}
}
}
Yes, they will. They're basically turned into a finally block.
So something like this:
using (SqlConnection cn = new SqlConnection(Global.sDSN))
{
....
}
is really turned into:
SqlConnection cn = new SqlConnection(Global.sDSN)
try
{
....
}
finally
{
cn.Dispose();
}
more or less - and the finally block is always executed, no matter what might have happened before in the try {.....} block.
When you use a using clause this is what's happening:
myobject = new object();
try{
// do something with myobject
}finally{
myobject.Dispose();
}
Hope this helps,
Best regards,
Tom.