This week I’m delivering a BizTalk development class for my colleagues, and during my preparation of demonstrations, I spent a few extra minutes confirming the behavior of members variables and atomic transactions.
Atomic transactions in BizTalk don’t necessarily behave like some folks expect. For instance, if a BizTalk orchestration calls a component with ADO.NET code which updates a database, and then raises an error later in the atomic scope, this will NOT cause that database operation to be rolled back. In another example, if you place a “send” shape inside an atomic scope, and a later operation fails, BizTalk doesn’t roll back the send operation. It’s standard design to use BizTalk “compensation” to execute logic to roll back any operations performed in the atomic scope.
Darren’s excellent BizTalk book states that there are realistically three scenarios where a developer will use atomic transactions in a BizTalk orchestration:
- Using a class not marked as serializable
- Calling a COM+ component that’s participating in the orchestration transaction
- Minimizing persistence points
However, don’t assume that atomic transactions in BizTalk are completely neutered. There are cases that you would want to use an atomic transaction as a part of your actual process.
In this scenario, my orchestration has two variables. One references a custom .NET data object (Employee), and the other variable is a simple string. After receiving a message into the orchestration, I instantiate those variables with default values and print them out.
Next, I have an atomic transaction which changes the value of both variables, prints them, and then throws an error. Immediately after the atomic scope, I print the variable values once more. As you can see here, I’ve also wrapped the atomic scope inside a long-running scope so that I can swallow the error and move on gracefully.
What do you expect to happen? Does the orchestration reset the member variable only, or also the custom .NET object’s member value?
As you can see, both variables start off with values of “started up”, inside the atomic scope the value switches to “changed status”, and after the exception is thrown within the atomic scope, the values get reset to their pre-atomic scope values. It makes perfect sense since changes occurring within the atomic scope don’t commit until the transaction is complete, but, it’s always useful to test it.
Now, this scope behavior does not extend much beyond this. If I add a function to my “Employee” class which writes a file to disk, and I call that operation within the atomic scope, the exception does NOT cause that operation to roll back. The file stays on my drive even after the orchestration has completed. That’s a scenario where compensation would be needed.
Technorati Tags: BizTalk