The best way to do your database work is to write it in the same transaction that is used to persist the workflow instance. That way your workflow state and your application database state will either both be visible or neither will be visible (you'll also be atomic in your writes so that a failure can't leave your app db state out of sync with your workflow persistence state).
There are two ways to include your work in persistence transactions. The first is to use a TransactionScopeActivity (TSA) in your workflow. Add a code activity as a child of the TSA and do your sql work in the code handler. When the TSA starts the WF runtime creates a System.Transactions.TransactionScope. The db work that you do in your code activity will automatically enlist in this transaction. The TSA completes the workflow instance will be persisted and the persistence service will use the same transaction as the TSA. Voila, you've got an atomic commit of your db work and the persistence work. This is a simple, natural transaction based programming model that is easy to use. However it assumes that you can dictate the structure of your workflow. If you can, by all means, use this approach
The second way is to write a class that implements IPendingWork. Your IPendingWork class will do your database work. In the workflow you can use a code activity (or a custom activity) to construct your IPendingWork class, hand it the data that it needs to write to the db and then add it to the WorkflowRuntime batch using the static WorkEnvironment.Workbatch.Add. When a persistence point occurs every IPendingWork item in the batch will have it's Commit method called. The persistence transaction is passed to Commit so that the work that you do will be consistent with the persistence work. This is a good way to go if you have users writing workflows that you need to run where you can't enforce that they use a TSA. You can write a custom activity that users can put in their workflow. This custom activity will create your IPendingWork class and add it to the batch. At the next persistence point your IPendingWork.Commit will be called and your data will be written atomically with the persistence data. This is a little more complex but it offers a very nice model if you have end users writing your workflows (or other users that may not understand what a TSA is for or when they should use it).
Thanks, Joel West MSFTE - SDE in WF runtime and hosting
This posting is provided "AS IS" with no warranties, and confers no rights |