views:

84

answers:

3

I have some scenarios where I need to have multiple calls to .SubmitChanges() on a datacontext, but I want to explicitly control the transaction myself to make it atomic. For a while I have been doing this by creating a connection, creating a transaction on that connection, then creating the datacontext and passing it both. Lets assume for now I dont want to use TransactionScope instead. My code looks like this:

Using conn As New SqlConnection("connection string...")
   conn.Open()
   Using trans = conn.BeginTransaction()
      Dim dc as new DataContext(conn)
      dc.Transaction = trans

      ' do some work 

      trans.Commit()
   End Using
End Using

I began using the Linq To SQL profiler and it breaks this code. For some reason they require you to use the .Connection property on the datacontext to create the transaction. It fails if you use the connection variable directly (which I think is silly). My question is, is it more appropriate to do it this way:

Using conn As New SqlConnection("connection string...")
   conn.Open()
   Dim dc as new DataContext(conn)
   Using trans = dc.Connection.BeginTransaction()
      dc.Transaction = trans

      ' do some work 

      trans.Commit()
   End Using
End Using

Which is the more widely accepted way to do this?

A: 
Product prod = db.Products.Single(p => p.ProductID == 15);

if (prod.UnitsInStock > 0)
   prod.UnitsInStock--;

using(TransactionScope ts = new TransactionScope()) {
   db.SubmitChanges();
   ts.Complete();
}

http://msdn.microsoft.com/en-us/library/bb425822.aspx

Raj Kaimal
"Lets assume for now I dont want to use TransactionScope instead."
Steven
A: 

use TransactionScope

http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx http://www.codeproject.com/KB/dotnet/TransactionScope20.aspx

this. __curious_geek
"Lets assume for now I dont want to use TransactionScope instead."
Steven
A: 

The second snippet doesn't seem appropriate to me. With the second snippet you need to create the transaction after creating the context, which is -at least- from a readability / maintainability perspective less useful. I try to imagine how your code would look when you need to create two DataContext classes, and create the transaction (only) after creating the first context. This makes it pretty hard to keep clean separated code.

I think you should send a mail to Hibernating Rhinos and ask if they fix this bug.

Steven
What is funny is my coworker seems to think this is the appropriate way, and I am finding many samples online that do it this way. I am just trying to find which way is the *proper* way
Jason
here are a couple examples:http://www.devart.com/blogs/dotconnect/?p=403http://geekswithblogs.net/robp/archive/2009/04/02/your-own-transactions-with-linq-to-sql.aspxhttp://stackoverflow.com/questions/542525/transactionscope-vs-transaction-in-linq2sql
Jason
@Jason: The second example is perfectly fine when you’re doing multiple SubmitChanges on a single data context. However, when you’re dealing with multiple DCs or dealing with a connection that is supplied from the outside, the situation is very different. I give examples of the first (http://stackoverflow.com/questions/2697658/is-there-an-automatic-way-to-generate-a-rollback-script-when-inserting-data-with/2697851, http://stackoverflow.com/questions/2220769/how-to-use-withnolock-in-linq-to-sql/2220937), because I assume the connection is not created at the same level as the data context is.
Steven
Thats the first example I have seen that does it the way I do. Its good to see I am not nuts. I prefer it since its seems cleaner to me, and connections/transactions can be passed around between methods. I use this scenario in legacy apps that use a mixture of ADO and L2S since we can't invest the time to retrofit the entire app.
Jason