Tuesday, 13 November 2007

New approach to Exceptions and Transactions handling

As much as I like the transactional support in the core of the X++ language, as much I dislike the connection between exception handling and transactions.

In my opinion transaction should be part of the syntax and have syntax based scope.

Here is my suggestion to Microsoft:

1) ban the standalone ttsbegin and ttscommit

2) replace it with special try-catch syntax , as drafted below:

try(new Connection())

{ //implicit TTSbegin

[do your stuff]

} //implicit TTScommit

catch(Exception::Error)

{ //implicit TTSabort.

[oops]

}

Both Oracle and MSSQL2005 support the nested transactions, and that would be ideal opportunity to use it.

conn = new Connection();

try(conn)

{ //implicit TTSbegin = BEGIN TRANS LEVEL1

try(conn)

{ //implicit TTSbegin = BEGIN TRANS LEVEL2

SalesFormLetterInvoice::post(SalesTable);

} //implicit TTScommit = COMMIT TRANS LEVEL2

catch(Exception::Error)

{ //implicit TTSabort = ROLLBACK TRANS LEVEL2

if(..cannot compensate the error...)

throw Error(....)

else

[compensate the error.]

}

} //implicit TTScommit = COMMIT TRANS LEVEL1

catch(Exception::Error)

{ //implicit TTSabort = ROLLBACK TRANS LEVEL1

[...]

}

That way each try-catch block is eligible to work, not only this started outside of transaction, and when needed each of them can operate own (sub) transaction.

It is also much less demanding on the developer, preventing improper or unbracketed use of ttsbegin and ttscommit. Normal (non db) try-catch bloack work as usually, allowing to catch X++ and CLR exceptions without unwanted rollbacks.