views:

4500

answers:

3

What are the differences between the classic transaction pattern in linq to sql like:

using( var context = Domain.Instance.GetContext() ) {

   try {
       context.Connection.Open();
       context.Transaction = context.Connection.BeginTransaction();
       /*code*/
       context.Transaction.Commit();
   catch(Exception e){
       context.Transaction.Rollback();
   }

}

vs the TransactionScope object

using( var context = Domain.Instance.GetContext() ) {
   using( var scope = new TransactionScope() ){
      try {
       /*code*/
       scope.Complete();
      }
      catch(Exception e){
      }
   }

}
+2  A: 

I believe they are fundamentally the same that the TransactionScope class will interface with the ADO.NET underlying connection to create and either commit or rollback the transaction. That the TransactionScope class was just created to make working with ADO.NET persistence cleaner.

Edit: Clarifying my statement with regards to casperOne's addition it is the TransactionScope that will create the transaction and the connection will then see the transaction that was created by the TransactionScope and use it since it's available to it.

Chris Marisic
@Christ Marisic: It's the other way around. The connection looks for the presence of a Transaction for the current thread, which would be created by TransactionScope. If there is one, then it enlists with the Transaction. The coordinator will then tell the connection to commit or rollback.
casperOne
+5  A: 

Linq2SQL will use an implicit transaction. If all of your updates are done within a single Submit, you may not need to handle the transaction yourself.

From the documentation (I've highlighted part of the quote for emphasis):

When you call SubmitChanges, LINQ to SQL checks to see whether the call is in the scope of a Transaction or if the Transaction property (IDbTransaction) is set to a user-started local transaction. If it finds neither transaction, LINQ to SQL starts a local transaction (IDbTransaction) and uses it to execute the generated SQL commands. When all SQL commands have been successfully completed, LINQ to SQL commits the local transaction and returns.

TGnat
+11  A: 

It should be noted that when using the TransactionScope there is no need for the try/catch construct you have. You simply have to call Complete on the scope in order to commit the transaction when the scope is exited.

That being said, TransactionScope is usually a better choice because it allows you to nest calls to other methods that might require a transaction without you having to pass the transaction state around.

When calling BeginTransaction on the connection object, you have to pass that transaction object around if you want to perform other operations in the same transaction, but in a different method.

With TransactionScope, as long as the scope exists, it will handle everything that registers with the current Transaction on the thread, making your code cleaner, and more maintainable.

On top of that, you have the added benefit of being able to use other resources that can participate in transactions, not just the connection to the database.

casperOne