Transaction Support in Service Instances

All Service instances are instantiated and executed as part of a TransactionScope in the SmartObjectBroker. The transaction option as specified on the SmartObject method determines the TransactionScopeOption.

We have three options:

  • Continue: TransactionScopeOption = Suppressed - No transaction, all services (executionblocks) will execute even if one or more fail.
  • Stop: TransactionScopeOption = Suppressed – No transaction, execution will halt immediately after first service execution fails.
  • Rollback: TransactionScopeOption = Required – A root transaction is created and will be the ambient transaction for all participating services to enlist in.

The concept of TransactionScope and ambient transactions is explained in more detail in the following MSDN article: http://msdn.microsoft.com/en-us/library/ms172152(v=vs.90).aspx

With ServiceTypes and ServiceInstances we have a variety of backends that could participate in the ambient transaction if need be. In the case of ServiceTypes that interface directly with SQL no additional configuration is needed because β€œany System.Transactions resource manager (such as SQL Server 2005 and higher) can detect the existence of an ambient transaction created by the scope and automatically enlist.” as per the article.

For other ServiceTypes without resource managers (e.g. Salesforce or SAP), the automatic handling of transactions are not possible. To address the requirement for transaction support, the ServiceSDK implements the IEnlistmentNotification Interface. This allows the ServiceInstance to either create and participate in a transaction specific to its back-end or to allow for compensation should a rollback occur.

By implementing the IEnlistmentNotification Interface the ServiceInstance has the option of overriding the following the four methods:

Name Description
Commit Notifies an enlisted object that a transaction is being committed.
InDoubt Notifies an enlisted object that the status of a transaction is in doubt.
Prepare Notifies an enlisted object that a transaction is being prepared for commitment.
Rollback Notifies an enlisted object that a transaction is being rolled back (aborted).

These methods will be invoked by the ambient TransactionScope (if it exists) and can therefore be utilized to handle the transaction events in the ServiceInstance. If a rollback or commit occurs on the ambient TransactionScope in the ServiceBroker, the executing ServiceInstances will be notified automatically and, if implemented, the appropriate transaction support method will be called.

Note that this will only work if the broker code for the data source supports COM+ transactions. E.g. SQL, Oracle and SmartBox.
The CRM client API and Active Directory don't participate in COM+ transactions.

The code snippet below shows how you can implement the various transaction support methods in your service broker. Again, the specific actions to take for supporting transactions depends on the target system being connected to.

///<summary>
/// Responds to the Commit notification./// </summary>
///<param name="enlistment">An Enlistment that facilitates communication between the enlisted transaction participant and the transaction manager during the final phase of the transaction.</param>
public override void Commit(System.Transactions.Enlistment enlistment) {
 if (enlistment != null) {
  // Indicate that the transaction participant has completed its work.
  enlistment.Done();
 }
}

///<summary>Responds to the InDoubt notification.///</summary>
///<param name="enlistment">An Enlistment that facilitates communication between the enlisted transaction participant and the transaction manager during the final phase of the transaction.</param>
public override void InDoubt(System.Transactions.Enlistment enlistment) {
 if (enlistment != null) {
  // Indicate that the transaction participant has completed its work.
  enlistment.Done();
 }
}

///<summary>/// Responds to the Prepare notification.
/// </summary>
///<param name="preparingEnlistment">An Enlistment that facilitates communication between the enlisted transaction participant and the transaction manager during the Prepare phase of the transaction.</param>
public override void Prepare(System.Transactions.PreparingEnlistment preparingEnlistment) {
 // Allow the base class to handle the Prepare notification.
 base.Prepare(preparingEnlistment);
}

///<summary>/// Responds to the Rollback notification./// </summary>
///<param name="enlistment">An Enlistment that facilitates communication between the enlisted transaction participant and the transaction manager during the final phase of the transaction.</param>
public override void Rollback(System.Transactions.Enlistment enlistment) {
 if (enlistment != null) {
  // Indicate that the transaction participant has completed its work.
  enlistment.Done();
 }
}