Flowing or propagating transactions in .Net


System.Transactions transactions are bounded to the appdomain. Which means that if you make in-appdomain calls from inside a TransactionScope, those calls will share the transaction. This also means that if you need to make a call outside the current appdomain, or outside the process, you will need to “flow” the transaction.


To flow a System.Transactions transaction, there are a few options:


a. if you are using serialization
 

//sender code
using(TransactionScope ts = new TransactionScope())
{
RemoteCallUsingSerialization(Transaction.Current, other parameter); // this is the call to other appdomain/process
// notice I added a new parameter of type System.Transactions.Transaction

ts.Complete();
}

//destination code
void RemoteCallUsingSerialization(System.Transactions.Transaction tx, other parameter)
{
using(TransactionScope ts2 = new TransactionsScope(tx))
{
// access transactional resourses like a database; this code will execute as part of the same transaction
ts2.Complete();
}
}


b. if you are not using serialization
 

//sender code
using(TransactionScope ts = new TransactionScope())
{
RemoteCall(TransactionInterop.GetTransmitterPropagationToken(Transaction.Current), other parameter); // this is the remote call
// notice I added a new parameter of type byte[]

ts.Complete();
}

//destination code
void RemoteCall(byte[] tx, other parameter)
{
using(TransactionScope ts2 = new TransactionsScope(TransactionInterop.GetTransactionFromTransmitterPropagationToken(tx)))
{
// access transactional resourses like a database;
// this code will execute as part of the same transaction
ts2.Complete();
}
}


c. if .Net 3.0 or higher is an option, you can use WCF and its support for transactions using attributes: http://msdn2.microsoft.com/en-us/library/aa347993.aspx


Remark: When the transaction is flown outside the current appdomain, it will get upgraded to a distributed transaction (or MSDTC transaction).


If you are not using .Net, see http://blogs.msdn.com/florinlazar/archive/2004/10/02/236965.aspx for propagating transactions in C++.

Comments (5)

  1. Sharas says:

    Hi,

    I just tried to pass the transaction instance to another AppDomain by AppDomain.SetData(string, object) method. In the code running in that AppDomain I get the transaction instace with AppDomain.CurrentAppDomain.GetData(string). By some magig it is promoted to distributed transaction by then (DistributedIdentifier is not an empty Guid). Can you please explain why this method is not in your list? Am I missing something?

    Regards,

    Sarunas Mazylis

  2. florinlazar says:

    To: Sarunas Mazylis

    AppDomain.SetData/GetData is using serialization to move the objects around.

  3. Sarunas Mazylis says:

    Hello again,

    Thanks for the answer.

    The problem I’m facing now is this:

    I need a way to execute peaces of code in different assemblys and I want those peaces to be executed in one transaction.

    Each assembly is loaded into new AppDomain and executed there. I flow the parent transaction to AppDomain. Then I unload that AppDomain.

    After unloading, when I try to use same parent transaction to execute another assembly in another AppDomain, I get Exception "The transaction has already been implicitly or explicitly committed or aborted." What am I doing wrong?

    Regards,

    Sarunas Mazylis

  4. florinlazar says:

    To: Sarunas Mazylis

    I noticed you posted the question on our forum at http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2915466&SiteID=1 which is the perfect place.