In .NET 2.0 (code-named "Whidbey"), Microsoft is introducing a bunch of slick enhancements and extensions to the programming model for transactions. Much of this is available through the new System.Transactions namespace. There's a whitepaper, Introduction to System.Transactions, available since April.

One of the nice things about Whidbey is the introduction of the TransactionScope class into the .NET Framework. This gives developers another option in programming their transactional work. A code snippet from that whitepaper shows the model I am talking about:

      using(TransactionScope scope = new TransactionScope()) {

        /* Perform transactional work here */

        //No errors - commit transaction

        scope.Complete();

      }

For those of you who have been around for 10+ years, it looks very much like Tran-C or Tran-C++, from Transarc's Encina (Graeme Dixon, the father of Tran-C, is now a distinguished engineer at IBM. Transarc was acquired by IBM in 1994).

It's a nice advance for .NET developers, and System.Transactions will bring other benefits, too. Some nice optimizations for one-phase commits, for example. But actually, you can get a similar the using(ts= new TransactionScope()){ } programming model with .NET v1.1.  The code looks essentially the same :

      using( TxUtil.ESTransactionScope ts = new TxUtil.ESTransactionScope()) {

          // do transactional work...

          ts.VoteToCommit = true;

        }

Now, some disclaimers: for .NET v1.1, this is not "built-in" to the framework, which means you, the apps programmer, have to provide and maintain the code for the TransactionScope class. Also, it depends on COM+ stuff that is available only in Windows Server 2003, and Windows XP SP2, so if you use Windows 2000, you can't get this.

But on the supported platforms, the code required to implement it yourself is pretty trivial, and examples abound. It has been called "Services without components", and the doc on MSDN mostly focuses on C/C++ developers, but it is also easily employed by .NET v1.1 devs using VB or C#.

A while back, Microsoft used this sort of programming model in a benchmark, and IBM had claimed that this was a really advanced technique: "To decide to code the distributed transactions with ServiceDomain classes ... shows a deep amount of technical skill." But it's not true. It's actually simpler than using ServicedComponents, in my book. Using the ServiceDomain class in .NET V1.1 is pretty straightforward. You can use transactions without deriving from the ServicedComponent class, and without configuring that component in the COM+ catalog. In short, it makes the high-performance Windows transaction engine more easily accessible to more programmers, and that's good.

Umm, Interop?

Yes, so the SwC programming model is nice, and it gets nicer in .NET 2.0 (aka "Whidbey"). The obvious next question here is, what about interop with non-Microsoft transactional resources? If you've been reading other entries on this blog you won't be surprised to learn that it just works. The SwC programming model does not introduce a new transaction engine. It is merely a new programming interface on the built-in platform transaction engine, formerly known as COM+. So, what works with the "traditional" COM+ programming model also works with SwC.

A great example is IBM MQSeries. In financial services enterprises, MQ is near-ubiquitous. It seems to be the preferred mechanism for linking anything to mainframe systems. And there are numerous programming interfaces for MQ - including C/C++, COBOL, RPG, Java, and, since September 2003, a .NET assembly. IBM introduced "the MQ Classes for .NET" as a new feature in MQ v5.3 CSD05, at that time. That allowed any .NET app to connect to MQ in a pretty simple manner. IBM did the integration with COM+, so an app that connects to MQ and another transactional resource manager, for example, MS SQL Server, can perform updates across both of them as a single logical unit of work, with ACID guarantees. The canonical example is, dequeue a message, then update a database based on the content of that message.

For an MQ app using the .NET classes from IBM, the MQ client library will automatically enlist in a transaction created programmatically via System.EnterpriseServices.ServiceDomain.Enter(). The doc in the IBM Redbook, WebSphere MQ Solutions in a Microsoft .Net Environment (SG24-7012-00) discusses transactions via COM+ configured components, but does not mention SwC. I am here to tell ya, when you access MQ, the same transactional guarantees are available whether you use traditional COM+ interfaces or SwC.

It's really pretty simple. Within the transactional work, you need to ask for syncpoints on the Get() or Put(), eg gmo.Options|= MQC.MQGMO_SYNCPOINT, or pmo.Options|= MQC.MQPMO_SYNCPOINT. The hardest part for me was installing and configuring Windows XP SP2 and MQ to allow XA transactions. I have a separate post for that.

I packaged up a sample, including source code, for you to try. For comparison purposes, I also included a sample that shows transactions spanning MSMQ and SQL Server, using the same programming model. (Like MQ, MSMQ also automatically enlists in ambient transactions.) Enjoy, and let me know what you think!

download the sample code

-Dino