Saturday, August 27, 2011

Transaction Timeouts in C#



After nearly 14 years doing Java development, I took the plunge this year and started working in .Net. It has it pluses and minuses over the Java environment and suite of tools but overall I have enjoyed the change. Below is one example of my many experiences in learning the Microsoft way.


As part of a oncology treatment planning GUI application, I created a Windows service to periodically pull oncology records from a Sybase database, aggregate the data and place it into a SQL Server 2008 R2 database. Putting the plan data into a database separate from the treatment database helps us ensure patient safety both by restricting access to the original treatment system as well as guaranteeing no write backs to the treatment database.
The records are written to the SQL Server database in a transaction using the Microsoft Distributed Transaction Coordinator (MSDTC). The code that does this is written in C# and uses the TransactionScope class. The records are pulled over and written in a batch as a single transaction, the transactions are not a record-by-record basis. This was the source of my trouble.


Because the data pull process will run at least daily (as well as on demand), typically the amount of data moved will be small. However, to validate extreme conditions, we ran tests on large data sets to ensure the application could handle large loads. When we deployed the software to our customer’s facility for beta testing it worked fine until they wanted to a much larger set of test data. This meant a pull with considerably more data than is normal. When we tested the same exact scenario in our lab on the East Coast (U.S.) to their test Sybase database located over 3000 miles away it worked fine. However, once we ran it on the customer’s server we began encountering problems. It turned out, the customer was testing on much older hardware with less bandwidth - by an order of magnitude.

Of course the first thing I checked was the debug log (log4net was really helpful here) and noticed a stack trace with a transaction error message during the batch write to SQL Server:

System.InvalidOperationException: The transaction associated with the 

current connection has completed but has not been disposed. The transaction must be
disposed before the connection can be used to execute SQL statements.

My first thought on seeing this error was that it was a data problem. I eyeballed the data in the database to see if anything stood out. It did not, and the same exact data worked just fine in our lab. I ran the test a few more times and noticed it did not fail at the same record but it did fail after processing around the same number of records. For example, if it failed at record ID 1474 on the first run it might fail at 1453 on the second run, 1500 on the third, and so on. From this evidence, it didn’t take long to figure out the error was being thrown at around one minute into the transactional write. From there it quickly became apparent that the transaction was timing out. I did a bit of research (thanks Google) to figure out where the transaction timeout was stored. The first place I checked was the SQL Server database settings, but it became quickly
apparent that the transaction timeout was controlled outside of the database. Next, I checked the Transaction Timeout setting in the Component Services:


I changed this to five minutes, restarted the MSDTC and my application. I retested, but no luck. The same transaction error occurred at the same time – one minute.

Back to Google to find another alternative. This time, I found a forum that talked about passing the TransactionScope a timeout parameter. I went back to the code and created a Timespan object of five minutes for the timeout (externally configurable of course).

using (TransactionScope tsc = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(0,5, 0)))

{
SQL Server inserts here...
tsc.Complete();
}


After testing locally, I rolled it out to the customer’s beta test and it ran as expected, completing the transaction.

Tuesday, August 16, 2011

Free eBooks from Microsoft Press

Episode 221 of Windows Weekly has a great tip by Paul Thurrott: Microsoft Press is giving away several eBooks in ePub and Mobi formats. The books can be found here. The eBooks cover introductory topics on Windows Server 2008 R2, SQL Server 2008, Visual Studio 2010, as well as several other areas. I've moved from Java development to .Net develop and plan to give these books a read.

Tuesday, February 10, 2009

Twitter and Idempotence

Idempotent is defined as the ability to remain “unchanged when multiplied by itself.1” This is a concept with which Twitter appears to be unfamiliar.

A little background. I finally decided to jump on the Twitter bandwagon. Going to Twitter.com to create an account, I was happy to discover my name was available. I created the account, PaulKlinker, eagerly hit submit, waited a bit, and got the fail whale screen. Not to be deterred by a fail whale, I hit the back button, reentered by data, submitted the request, and got the fail whale again. Once again, I backed the browser up, entered the data, submitted and...Success! I was now the proud owner of a twitter account.

Going into my account, I put in my cell phone number so I could get text messages. Next, I followed John C. Dvorak, and then entered some profile info. I sent a test tweet and finally was all ready to start receiving messages. A couple days later a colleague of mine even started following me.

But, I began to realize I wasn't getting any tweets. Hmm? Checking my email I noticed I had two new Twitter account confirmations. Uh oh. Logging into Twitter confirmed that two accounts were created for PaulKlinker. Apparently one account can send Tweets and the other can receive.

So I had two accounts, with the same name, created during my new account creation process. This is where the importance of idempotence comes in. Looking again at the definition of idempotent, “unchanged when multiplied by itself", means no matter how many times you submit the request to create an account using the same parameters, it only creates one account. When developing network based applications certain operations must be idempotent and Twitter developers need to learn this concept, or at least implement it correctly. I am still dealing with the mess, but more on that later.

Saturday, January 31, 2009

Google Malware Bug

Like many others, I was hit with Google's harmful site message. I needed to return a textbook, so this morning I ran a search on Google for the Virginia Tech bookstore. I got the "This site may harm your computer." message, except of course for then Sponsored Links; they worked fine.



Clicking on the first link returned led to Google's blocked site page. I had just rebooted my MacBook after a MacOS update and for a brief moment thought it might be a result of that. The same search at Yahoo quickly showed it was a Google problem as the Yahoo search was successful.




Curious as how they handled the redirection, I saved the page. Examining the page source showed the active link to Virginia Tech's bookstore, nvgc.bncollege.com, was replaced with the redirection to the malware warning but that the original link was still available in the page source link.
So, if the malware warning is real and you are intent on visiting the site, it looks like you can find the link in the page source.

Google has a good description of the bad link problem on their blog.