Root object created from root object...

Root object created from root object...

Old forum URL: forums.lhotka.net/forums/t/2835.aspx


kbcb posted on Tuesday, May 08, 2007

I have two root objects, Document and DocumentQueueItem.

When a new document is created, business requirements state that the document needs to be added to the document queue.

The problem I have is with where the DocumentQueueItem should be built and when it should be saved. It seems to me that with this being a business requirement/business logic, the DocumentQueueItem should be built and saved when the document is saved (which means the DataPortal_Insert method). My code would look like this:

class Document
{
   void DataPortal_Insert( )
   {
      using ( SqlConnection newConnection = new SqlConnection(...))
      {
         // Call my database's procedure to insert my document object data

         DocumentQueueItem newDQI = DocumentQueueItem.NewDocumentQueueItem(this);
         newDQI.Save();
      }
   }
}

I did the above, and initially (at runtime) my program complained saying that MSDTC was not available. I figured out that this was because my DataPortal_Insert on Document creates and opens a new connection and that my DataPortal_Insert on DocumentQueueItem ALSO creates a new connection. MSDTC needed to be used because they are transacted methods. So, I started my "Distributed Transaction Coordinator" service and it worked just fine.

However, this doesn't seem right to me. I have heard that DTC is very slow, which, for such a commonly used part of my program, is not a good thing.

There has got to be a way for me to achieve this type of concept without overloading all my methods with a version that accepts a SqlConnection, and without testing whether or not my SqlConnection is in my LocalContext all the time.

Any help on the issue would be great. Thanks!

RockfordLhotka replied on Tuesday, May 08, 2007

You must be using a TransactionScope? Otherwise the DTC wouldn't come into play.

First thing to consider: if you are only talking to one database, even multiple tables, you do not need the DTC. You can get transactional protection purely through ADO.NET transactions, or through TransactionScope local transactions.

What is happening to you is that you are being hit by a well-known oversight of TransactionScope. It turns out that TransactionScope enlists the DTC as soon as you open a second database connection - even if it is to the same database (which you'd think it shouldn't).

So what you need to do is open one database connection and reuse it across all your objects. This is the reason I added Csla.ApplicationContext.LocalContext - you can see examples of using it in my ebook.

However, in your case there's a twist, because your second root object would need to use the pre-opened connection, which is not normal. My suggestion though, is to just see if LocalContext has the connection, and only open a connection if you need it, otherwise just use the connection from LocalContext.

kbcb replied on Tuesday, May 08, 2007

Any idea why it is that the DTC is not smart enough to figure this out?

RockfordLhotka replied on Tuesday, May 08, 2007

It is the transactionscope object's job to do this. I think this is an oversight in version 1 of the transactionscope feature.

Rocky


-----Original Message-----
From: "kbcb"
To: "rocky@lhotka.net"
Sent: 5/8/2007 6:59 PM
Subject: Re: [CSLA .NET] Root object created from root object...

Any idea why it is that the DTC is not smart enough to figure this out?

Copyright (c) Marimer LLC