Finding out if an exception occurred in a finally block. (.NET 2.0)

  • Thread starter Thread starter Peter Strøiman
  • Start date Start date
P

Peter Strøiman

Hi.

Since my situation is a little complex I have simplified it for this post.
I start a database transaction. Do some work with it in a try-finally block,
and in the finally block I dispose resources. I would like to in my finally
block detect if we are leaving because of the code actually just leaving the
block (normally or through a return statement) or an exception occurred. If
we are leaving normally I want to commit the transaction, and if we are
leaving because an exception is thrown, I want to abort the transaction.

SqlConnection conn = CreateNewOpenConnection(...)
try
{
SqlTransaction trans = conn.BeginTransaction()
// do work
}
finally
{
if (exception occurred)
trans.Rollback();
else
trans.Commit();
trans.Dispose();
conn.Dispose();
}

Is this possible. I'm using the .NET framework 2.0

Thanks in advance,
Peter Strøiman
 
Peter said:
SqlConnection conn = CreateNewOpenConnection(...)
try
{
SqlTransaction trans = conn.BeginTransaction()
// do work
}
finally
{
if (exception occurred)
trans.Rollback();
else
trans.Commit();
trans.Dispose();
conn.Dispose();
}

Is this possible. I'm using the .NET framework 2.0

You wouldn't do it that way, but it's possible to do what you describe.
Just put your code like this:

SqlConnection conn = CreateNewOpenConnection(...)
SqlTransaction trans = conn.BeginTransaction()

try {
// do work

trans.Commit();
}
catch {
trans.Rollback();
}
finally {
trans.Dispose();
conn.Dispose();
}

Now, two other things I should mention: First, you should not, like I do
in the sample, catch all exceptions, but you should find out which
exceptions you can actually handle here and only catch those. Second,
you can use the "using" statement, which implies a try/finally and a
dispose, so the code would be even better readable, like this:

using (SqlConnection conn = CreateNewOpenConnection(...)) {
using (SqlTransaction trans = conn.BeginTransaction()) {
try {
// do work
trans.Commit();
}
catch {
trans.Rollback();
}
}
}

Hope this helps!


Oliver Sturm
 
Thanks for your reply.

As I said in my original post, this a simplification of my problem, but my
problem is much more complex, so I cannot do as you propose. The fact is,
that all my logic handling the transaction is wrapped in a class, that is
disposed using the using statement.
But in my transactionhandling's Dispose implementation I want to determine
if an exception was thrown

using( TransactionHandling t = new TransactionHandling())
{
}
 
Hi

I think the finally is target at handle the code finished job, somewhat
like the deconstructor.
Its code should be not related with whether there is an exception.

I think you may try to change your design to use the try...catch...finally
block.

Try
{
//the code which may have exception
}
//handle the proper exception
catch(exception A)
{
}
catch(exception B)
{
}
finally
{
//clean up job
e.g. the try block may create a temp file, then the file need to be deleted
whenever the exception occur.
}

If you do want to do that, I think a possible approach is to use bool flag,
to set it to true at the every end of the try block, so in the finally
block you can detect the bool flag to know if the try is exit at the end.

BTW:
So far Whidbey issue is not officially supported, so the behavior may vary
after the finally release.
For Whidbey issue, you may try to report in the vs2005 forum.
http://lab.msdn.microsoft.com/vs2005/community/


Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
Peter said:
As I said in my original post, this a simplification of my problem, but my
problem is much more complex, so I cannot do as you propose. The fact is,
that all my logic handling the transaction is wrapped in a class, that is
disposed using the using statement.
But in my transactionhandling's Dispose implementation I want to determine
if an exception was thrown

using( TransactionHandling t = new TransactionHandling())
{
}

I understand, but I still think you should handle things differently :-)
For example, you could rethrow the exception to be caught outside your
transaction handling encapsulation. Or, if you absolutely want to break
out of the standard exception handling system, you could store away the
exception information in a catch block inside the class and evaluate
that information from the outside later on.

I thought I had at some point heard or read something about a way to
detect whether "there is currently an exception". But I was unable to
find whatever it was I had in mind there. The other thing is: Such a
mechanism could obviously only work if the exception was still "active"
at that point, in contrast to having been swallowed by a catch block
earlier on. So if the exception is really active at this point in your
code, what would keep you from simply catching it with a catch block?

What you are asking is, apparently, "how do I find out if an exception
was thrown before I got to the point where I'm now". The answer to that
will usually be yes, of course, because exceptions are thrown and caught
many times during the run of a .NET application (even though we all know
they shouldn't be used for flow control in the main execution path). Now
you are going to modify the question to say "I'm not interested in all
exceptions that might have been thrown before I got to the current
point, only in those that might have been thrown during the use of the
TransactionHandling class." So if that is your actual question, let me
ask again: Why don't you put an external try/catch around the use of the
TransactionHandling class and find out?



Oliver Sturm
 
Back
Top