Reputation: 410
Take this code sample:
string status = "ok";
SqlCommand cmd=null;
SqlTransaction trans=null;
try
{
cmd = defs.prepquery("");
trans = cmd.Connection.BeginTransaction();
cmd.Transaction = trans;
}
catch (Exception ex)
{
status = defs.logerror("initalizing sql transaction:" + ex.ToString());
return status;
}
try
{
if (oper == "submit")
{
cmd.CommandText = "update DCM_Mapping_Sessions set StatusID=2 " +
"where MappingSessionID=" + mpsid + "";
cmd.ExecuteNonQuery();
}
else if (oper == "delete")
{
// .......etc etc
}
catch(Exception ex2)
{
//rollback , close the connection
// handle the ex
}
// if everything is ok , comit the transaction and close the connection
}
So my question is: What happens with the objects in the try block when an exception occurs ? Does C# allows me to be lazy and destroys the objects(destroying the pending transaction meaning rollback) and closes the connection if an exception occurs ?
I come from a C\C++ background so i am doing my stuff as above to be safe and not end with a transaction open if an exception occurs somewhere below.
Upvotes: 1
Views: 1088
Reputation: 35696
Short answer, no.
Longer answer, yes but far too late.
This is why we have the finally
clause and the using
block. You are responsible for calling the close or dispose.
They will get closed or disposed later when the garbage collector is forced to do this "slowly" for you but, there will be an indeterminate period where your expensive resources are wasted unesscessarily.
Something like this would be preferable
using(var connection = defs.GetConnection())
using(var cmd = new SqlCommand())
{
cmd.Connection = connection;
switch(oper)
{
case "submit":
cmd.CommandText = "update DCM_Mapping_Sessions" +
"set StatusID=2" +
"where MappingSessionID=" + mpsid;
case "...
}
try
{
cmd.ExecuteNonQuery();
}
catch(SomeSpecificExceptionIShouldActuallyHandleHere ex)
{
...
}
}
Possible injection attack aside.
Upvotes: 0
Reputation: 498904
You should be disposing/closing the connection and transaction.
The best way to do so is to wrap the creation in a using
statement.
Provides a convenient syntax that ensures the correct use of IDisposable objects.
In essence a using
statement wraps the creation of the objects in try{}finally{}
blocks to ensure proper disposal.
using(var cmd = defs.prepquery(""))
using(var trans = cmd.Connection.BeginTransaction())
{
}
Upvotes: 4
Reputation: 16846
Have a look at try-finally
.
It does exactly what you're asking for.
So your code looks like:
try
{
//try something
}
catch(Exception ex2)
{
// handle the ex
}
finally
{
//rollback , close the connection
}
Upvotes: 5