Andy's observations as he continues to attempt to know all that is .NET...

Friday, January 12, 2007

TransactionScope and DataAdapters

Recently I had to write some code that persisted changes too two DataTable's to a SQL Server database, with both updates inside a single transaction. So since I was using .NET 2.0 I decided to use TransactionScope.

using( TransactionScope tx = new TransactionScope()))

{

    firstTableAdapter.Update( firstTable );

    secondTableAdapter.Update( secondTable );


 

    tx.Complete();

}


 

I was careful to ensure that both adapters used the same database connection object, however there was still a nasty side effect. First a bit of background

In order for a resource manager (in this case SQL Server) to take part inside a transaction it must first enlist in the transaction, SQL server determines if to do this when a connection is opened. Opening a connection when there is a transaction associated with the current thread will result in SQL server placing that connection inside a transaction, if no other enlistment has happened then SQL server will create a local transaction and thus manage the transaction.

If another resource manager wishes to enlist in the transaction then no one resource manager can be responsible for coordinating the transaction and the DTC is invoked (Distributed Transaction Coordinator), the role of the DTC is to ensure the properties of the transaction across multiple resources. Such that a failure to commit one set of resources through one resource manager causes a rollback in the other. SQL Server is the only resource manager that currently allows the promotion of a local transaction to a distributed transaction; other resource manages like MSMQ will always create a distributed transaction irrespective of the number of previous enlistments.

Ok, so to sum up if you enlist multiple resource managers inside a single transaction the DTC is invoked and the transaction becomes a distributed transaction. The obvious consequence of this is that the transaction management is now more expensive. So we obviously want to avoid having a distributed transaction unless we really need to.

When first playing with TransactionScope we can end up with a distributed transaction when from a high level logical perspective it might seem strange.


 

using( TransactionScope tx = new TransactionScope() )

{


 

    conn.Open();

        // Do DB Work

conn.Close();


 

conn.Open();

        // Do DB Work

conn.Close();


 

tx.Complete();

}


 


 

In the above example our transaction is promoted to a distributed transaction, why because on the second open SQL Server will attempt to enlist in the transaction, because there is already a transaction enlisted System.Transaction will attempt to promote the existing transaction to be managed by the DTC, and the new transaction will also be managed by the DTC. This does seem odd at first since you are in fact only using a single Resource Manager, there is a rumour that this will be fixed in the future. If you do not have the DTC service running on your machine the code above will throw an exception. If you have the DTC running then the code runs to completion, and you are non the wiser of the promotion, except for a slight pause. To see when the promotion has taken place simply make a call to the function below at the various points to see the transaction identifier.

private
static
void PrintTransaction(Transaction transaction)

{


Console.WriteLine("Local Id = {0}" , transaction.TransactionInformation.LocalIdentifier );


Console.WriteLine("Global Id={0}" , transaction.TransactionInformation.DistributedIdentifier);

}


 

Back to the data adapter example, when the data adapter attempts to do an update if the connection is not currently open it opens the connection and performs the update. If it opens the connection it would be polite for it close the connection when it is done. So when the first Update runs on opening the connection it creates a local transaction which gets enlisted, when the second update runs it also needs to open the connection and so it enlists a second transaction and thus causes the behaviour observed above. To fix the problem we simply have to ensure that the connection is only opened once.

using( TransactionScope tx = new TransactionScope()))

{

    conn.Open();

    try

    {

        firstTableAdapter.Update( firstTable );

        secondTableAdapter.Update( secondTable );


 

        tx.Complete();

}

finally

{

    conn.Close();

}

}


 

Now when the calls are made to update the data adapter sees that the connection is already open and thus the sql commands now run in the context of the existing transaction and no promotion is necessary. It is therefore essential that when you create the data adapters you create them with the same connection object you are using inside the transaction scope.

All this poses the question how can I ensure that I don't accidently cause a promotion to take place; there are two solutions that come to mind

  • Disable the DTC on your machine
  • Add a Debug.Assert prior to calling the outer Complete

The only way I could find to determine if a promotion had happened was to look at the Distributed Transaction Identifier.

Debug.Assert(IsInDistributedTransaction() == false);

tx.Complete();


 

...


 

private
static
bool IsInDistributedTransaction()

{



return ((Transaction.Current != null) &&

(Transaction.Current.TransactionInformation.DistributedIdentifier != Guid.Empty));}


 

So whilst TransactionScope has certainly improved the programming model for transactions by hiding a lot of the complexities required for distributed transactions it is essential to understand how it works if you are to avoid accidently creating a distributed transaction.

Friday, January 05, 2007

WPF Pong


 

Couldn't keep still over the xmas break, my kids were playing some of those classic games we used to play as kids although now inside a tiny console you plug in to your tv. This got me thinking about writing a classic game using WPF, not being much of a games writer I kept things simple and decided to implement the classic game Pong...My main aim is to continue to ramp up on WPF, one area I wanted to explore further was the use of Content Templates and styles, what I wanted to be able to do was not only clearly separate UI layout from UI behaviour but also allow different Skins to be applied to the game one being the classic black and white look another being a more 21st Centaury look and feel.

To implement Skining in WPF you make use of Styles contained in resource dictionaries, when a control makes reference to a named style the control tree is walked for each control its resource dictionary is searched for a style by that name if none is found the search continues up the tree. Styles allow you to set properties of the control, very similar to ASP.NET skins. So in the case of the bats you can set a style that sets the colour, width and length of the bats. You can then apply this style to both player one's and player two's bat keeping both bats looking the same. In order to allow the interchanging of Skins I placed all the resource definitions into their own resource dictionaries. Each Skin is then an instantiation of a resource dictionary, when the window is launched I simple associate my window resource dictionary with the currently selected skin. When any of the controls wish reference styles located in resources they walk up the control tree looking for the resource and should find it in the resource dictionary associated with the window. If the user wishes to change the current skin I simply change the resource dictionary associated with the window and the look feel changes to reflect the new skin.

this.Resources = newSkin;// this is the current window


 

Below is an extract from GameWindow.xaml, the style of the stack panel is defined through a resource named StatusPanel, notice that DynamicResource is used as opposed to StaticResource. If you want to have any changes in resources immediately reflected then you need to bind using a DynamicResource, these are slightly more expensive since the infrastructure needs to keep track of any changes.

<StackPanel
Grid.Column="0"
Grid.Row="3"
Style="{DynamicResource StatusPanel}" >


 

One really cool feature of WPF is the ability to change the inner content of a control via the template property. I used this to great effect when defining for displaying the scores using block character style numbers. I used a data trigger to select the appropriate inner content template based on the value of the score.

When I have some more free time I want to add WPF animation effects so that the bat shudders when the ball hits it...Oh and my QA engineer ( AKA my son ) wants to enhance the game so you can move the bats forwards and backwards too...( "Just like real tennis." )

Oh I also perhaps need to have some instructions in regard to keys etc...but for now

A and Z player one

K and M player two

And Space to serve..

First to 9 wins...

When I first started hearing about WPF and how designers would now rule over UI I I started to get the same feelings I had when I first saw VB 6, but what seems to be coming clear whilst the designers can really do cool stuff they really need to have good exposure to the underlying model, so there certainly is still a significant role for us UI developers in exposing the appropriate information all be it perhaps slightly removed from the coal face...


 

You can download the full source from WPFPong , or for any Click Once Jen fans you can install it via ClickOnce

About Me

My photo
Im a freelance consultant for .NET based technology. My last real job, was at Cisco System were I was a lead architect for Cisco's identity solutions. I arrived at Cisco via aquisition and prior to that worked in small startups. The startup culture is what appeals to me, and thats why I finally left Cisco after seven years.....I now filll my time through a combination of consultancy and teaching for Developmentor...and working on insane startups that nobody with an ounce of sense would look twice at...