views:

69

answers:

4

This question is related to my question: http://stackoverflow.com/questions/3072986/sql-server-and-transactionscope-with-msdtc-sporadically-cant-get-connection

I'm doing some transaction programming using the .net TransactionScope class. If I understand correctly, I can do some SQL operations within a transaction by wrapping the SQL calls inside a using ts as new TransactionScope() block, or by using new TransactionScope() and then TransactionScope.Dispose() at the end.

To commit the transaction, MSDN says to use TransactionScope.Commit(). Supposing that I want to rollback the transaction under certain circumstances, is it sufficient to simply call TransactionScope.Dispose() without calling the Commit method first? Is that good practice, or is this supposed to be done some other way?

+3  A: 

If you call TransactionScope.Dispose() (either by a using block or by calling the Dispose method yourself), it will rollback the transaction unless you tell it t commit first. By putting in a Transaction.Rollback, you are explicitly telling other programmers that is what you intend on doing.

I would probably add it for sake of clarity that this action was intended in that circumstance. The other thing about not explicitly adding the rollback command is that you are assuming that the Dispose method will always behave in this manner. In reality this will probably be the case, but making that assumption is risky. It's always better to explicitly roll it back instead of hoping that it will be done for you.

Kevin
Just a quick follow-up question: Is there any circumstance under which I can cause my transaction to hang in the aether by calling `Dispose` at the wrong time?
Rice Flour Cookies
Cause it to hang? What could happen is that if you call dispose and the transaction isn't committed, it will have to roll back everything that it is ready to commit, that could in theory cause it to "hang" while it puts the system back in a ready state.
Kevin
As I mentioned in the other question I link to, I'm having trouble where some of my transactions are getting "locked" on a SQL server, as if the transaction is neither committed nor rolled back, and then other users cannot access the data on the server. What is the correct way to use `Transaction.Rollback()` with `TransactionScope`? Rollback is a member of Transaction, but Rollback is not a member of TransactionScope.
Rice Flour Cookies
+1  A: 

I've always encased the TransactionScope in a Using block, since that automatically calls the Dispose if there's an unhandled exception that prevents the transaction from completing successfully.

rwmnau
if you've called complete before you exit the using scope the transaction will still commit
Rune FS
+1  A: 

if you know you want to rollback then do that explicitly. You are not quaranteed that Dispose will rollback (in the case where complete has been called, the transaction will be comitted when you call Dispose)

to your question about using or new/Dispose they are not equivalent

using(var ts = new TransactionScope())
{
}

is equivalent to

TransactionScope ts;
try
{
  ts = new TransactionScope();
}
finally
{
  ts.Dispose();
}

to answer your follow up question no if you call Dispose you will not have you transaction "hanging around" it will either commit or rollback. However if you use the new/dispose as you wrote it (no finally block) you can have a situation where dispose isn't called when you expect it to be (in the case of an exception)

Rune FS
+2  A: 

The intent of the TransactionScope class, as I see it, is to make transactions as foolproof as possible to the application developer, and to this end, make the recommended means of aborting a transaction be the one with the least extra thought. I believe (based on the documentation of TransactionScope) a simple Dispose is the recommended means of ending the transaction, and if it hasn't been committed, it will be rolled back.

BlueMonkMN