For methods marked with the AutoComplete attribute, do either of the following:
- Propagate the SqlException back up the call stack.
- Wrap the SqlException in an outer exception and propagate that to the caller. You might want to wrap the exception in an exception type that is more meaningful to the caller.
Failure to propagate the exception will result in the object not voting to abort the transaction, despite the database error. This means that other successful operations made by other objects sharing the same transaction stream might be committed.
The following code catches a SqlException and then propagates it directly to the caller. The transaction will ultimately abort because this object's consistent flag will automatically be set to false when it is deactivated.
// Open the connection, and perform database operation
. . .
catch (SqlException sqlex )
LogException( sqlex ); // Log the exception details
throw; // Rethrow the exception, causing the consistent
// flag to be set to false.
// Close the database connection
. . .
Note If you have multiple catch blocks, it is easier to call ContextUtil.SetAbort once at the start of a method, and call ContextUtil.SetComplete at the end of the try block. In this way, you do not need to repeat the call to ContextUtil.SetAbort within every catch block. The setting of the consistent flag determined by these methods has significance only when the method returns.
You must always propagate exceptions (or wrapped exceptions) back up the call stack because this makes the calling code aware that the transaction will fail. This allows the calling code to make optimizations. For example, in a bank funds transfer scenario, the transfer component could decide not to perform the credit operation if the debit operation has already failed.
If you set the consistent flag to false and then return without throwing an exception, the calling code has no way of knowing that the transaction is bound to fail. Although you could return a Boolean value or set a Boolean output parameter, you should be consistent and throw an exception to indicate an error condition. This leads to cleaner and more consistent code with a standard approach to error handling.