Last week I visited a client and we were chatting about how to handle transactions efficiently in .NET. Inevitably we started talking about Java and the ability to be able to tie a transaction context to a specific thread.
In .NET this sort of thing is actually relatively easy to do by using COM+ and the ServiceConfig, ContextUtil and ServiceDomain classes to run distributed transactions without the requirement to go through subclassing of ServicedComponent.
However, if you’re not using a DTS compliant database COM+ becomes a problem (in this case the data was going to be a Fox backend migrating to SQL Server eventually). Also, COM+ transactions are significantly more expensive than transactions managed via plain ADO.NET/T-SQL code.
Soooooooo… we were talking about creating some sort of context object that gets tied a thread and could act as a global container for thread global resources, which might be a very good fit for a transaction coordinator that a business object or data layer can go to get information about the current transaction state.
Great idea, except, I couldn’t think of a built-in way to create an object that is tied to a specific thread. I don’t think there’s a built in facility to tie properties to a thread.
But with a little bit of work it’s relatively easy to implement:
///
/// Very simplistic class that allows tying properties to an active thread.
/// Note this class does nothing to deal with cleanup of entries
/// if the thread goes away.
///
public class ThreadContext
{
private static Hashtable _Properties;
static ThreadContext()
{
_Properties = new Hashtable();
}
///
/// Adds a name value pair to the thread context. Pass a null
/// value to remove an entry.
///
///
///
public static void SetProperty(string Key,object Value)
{
Key = AppDomain.GetCurrentThreadId().ToString() + Key;
if (_Properties.ContainsKey(Key) )
{
if (Value == null)
_Properties.Remove(Key);
else
_Properties[Key] = Value;
}
else
_Properties.Add(Key,Value);
}
///
/// Retrieves a value from the thread context by its key name
///
///
///
public static object GetProperty(string Key)
{
Key = AppDomain.GetCurrentThreadId().ToString() + Key;
if (_Properties.ContainsKey(Key) )
return _Properties[Key];
return null;
}
}
So now you can do something like this:
ThreadContext.SetProperty("ActiveTransaction",this.DAL.Transaction);
…
IDbTransaction Transaction = ThreadContext.GetProperty("ActiveTransaction")
as IDbTransaction;
if (Transaction != null)
this.ChildObjects.DAL.Transaction = Transaction;
Of course this sort of code actually belongs into the data access layer to support nested transactions. To make this a little easier yet it might be useful to create another wrapper class for the TransactionContext:
///
/// Wrapper class that exposes a static transaction property that
/// is tied to an underlying thread
///
public class TransactionContext
{
public static IDbTransaction ActiveTransaction
{
get { return ThreadContext.GetProperty("ActiveTransaction") as IDbTransaction; }
set { ThreadContext.SetProperty("ActiveTransaction",value); }
}
}
So, now you can simple check for an Active Transaction with:
if (TransactionContext.ActiveTransaction != null)
This is overly simplistic for a Transaction manager of course, but it’s a starting point. From here you’d have to hook into the DAL to check for active Transactions and make sure that these transaction objects get cleared out when a transaction completes or rolls back.
There may be other places where it’s useful to attach properties to a specific thread. Realize that if you use something like this especially in a multi-threaded environment like ASP.NET you’ll want to be REAL careful about cleaning up after yourself and releasing any thread storage whenever you don’t need it any longer, because ASP.NET will reuse resources. So in the transaction example above you’d want to clear out the transaction object every time. Failure to do so can end up creating resource leaks and potentially more severe problems - with transactions that aren't properly handled a database lockup is not far off for example.
Other Posts you might also like