<cftransaction>
<cfscript>
try
{
variables.LocationCodeDataDelegate.UpdateLocationCode(arguments.LocationCodeView.GetLocationCode());
arguments.Event.AddMessage("Location code updated successfully.");
arguments.Event.SetError(false);
}
catch(any ex)
{
arguments.Event.SetError(true);
arguments.Event.AddMessage("There was an error updating the location code.<br><br>#ex.message# The error occured on or around line #ex.TagContext[1].line# on file #ex.TagContext[1].template#<br>#ex.detail#",true);
}
</cfscript>
</cftransaction>
Now I had incorrectly assumed that if my UpdateLocationCode function would throw an error that the transaction would be rolled back automatically. It turns out that since that error is caught and normal processing continues after the catch tag that this transaction commits just fine.
The fix for this problem is a simple one. In my Event object I have a boolean property called Error that is defaulted to true, only when the code inside my try block completes is it set to false. All I need to do is check my Event object for an error condition right before my tag and rollback the transaction if the error condition is true as shown below:
<cftransaction>
<cfscript>
try
{
variables.LocationCodeDataDelegate.UpdateLocationCode(arguments.LocationCodeView.GetLocationCode());
arguments.Event.AddMessage("Location code updated successfully.");
arguments.Event.SetError(false);
}
catch(any ex)
{
arguments.Event.SetError(true);
arguments.Event.AddMessage("There was an error getting the location code.<br><br>#ex.message# The error occured on or around line #ex.TagContext[1].line# on file #ex.TagContext[1].template#<br>#ex.detail#",true);
}
</cfscript>
<cfif arguments.Event.GetError()>
<cftransaction action="rollback" />
</cfif>
</cftransaction>
Why not
ReplyDelete<cftransaction>
....
<cftransaction action="commit">
<cfcatch type="ex")>
<!--- log error message --->
<cftransaction action="rollback">
</cfcatch>
</cftransaction>
IMHO, it is better because programmer's intention is more clear/explicit, as such easier to understand. Also, when you work with savepoints, and rollbacking is based on error handling not business logic, this will be the way how you'll handle it.
I agree, but this is not always practicle in all cases either.
ReplyDeleteFor example, I might have a transaction block that calls one or methods that throw errors and this is normal coding style.
The decision is to catch anything that you need to catch and if doesn't involve the datbase then normal processing should be assumed. If how ever that the catch has caught a databse exception then one should just rethrow the error so the outer code (the code that called the function) can then rollback if needed.
Thanks for the comments.
ReplyDeleteMarko, I do like the way that looks.
Andrew, I'd like to see an example of what you are talking about.