System.Transactions and legacy code

System.Transaction is the latest incarnation of transactions from Microsoft.  It first showed up on the scene with the release of .NET Framework 2.0.  Today, however, was my first interaction with it.  As with most things I do, I happened to be trying to do something that apparently no one else in the world as done (okay, probably not true, but when I ran into problems I sure didn’t find much help out there).

My goal was to create some WCF services that would expose some legacy C++ functionality.  The C++ functionality was doing updates to some database tables using ADO (the old ADO, not the new ADO.NET).  My approach to doing this seemed quite straight-forward to me so I naturally figured it wouldn’t take me long.  I was going to create a new C++ library containing managed code that would turn around and call the legacy functions that are exported from another C++ library.  My new C++ library could be compiled into a nice .NET assembly that I would reference from the C# WCF library.  The WCF service in the C# library would just call the "wrapper" class in the new C++ library, which in turn would call the legacy function.  Piece o’ cake, right?

Getting things built and compiled was easy.  Getting things to work, however, was not.  My issue was that the database updates that occurred within the legacy code did not occur within the WCF transaction that was created.  So, if I had to rollback the transaction I would be screwed because the legacy updates wouldn’t get rolled back. 

I tried several different approaches.  I even went down the path of creating a ServicedComponent as my "wrapper" and using EnterpriseServices.  It was that path that led me to the answer (or at least one answer that seems to work).  The approach I ended up with is to put a "using (TransactionScope ….)" statement in my WCF operation that wraps the call to the C++ wrapper.  The not-so-obvious trick, however, is that the TransactionScope constructor needs to be the one that allows me to specify EnterpriseServicesInteropOption = Full, like this:

using (TransactionScope s = new TransactionScope(Transaction.Current, new TimeSpan(0, 2, 0),
    EnterpriseServicesInteropOption.Full))  {
// call the legacy component
s.Complete();
}

This made things work like a charm and a did NOT need to have the wrapper actually be a ServiceComponent.

Enterprise Library

Microsoft’s Enterprise Library has been around for a few years now.  The current release is version 4.0 and you can download it from CodePlex - patterns & practices Enterprise Library.  Enterprise Library is a set of "application blocks" that address some of the common, technical services that are often needed when building enterprise applications.  The source code is available for you, but in general you want to leave it as is.  Many of the blocks are constructed so they can be easily extended by creating additional providers that you can just "plug-in".

I confess that I haven’t used Enterprise Library very much.  I just recently started taking a close look at what it can do and thinking about how I to best leverage some of the blocks.  It definitely has some nice features like Logging and Data Access that you can use and benefit from even for some smaller scale applications.

« Previous PageNext Page »