1

Code

double timeout_in_hours = 6.0;
MyDataContext db = new MyDataContext();
using (TransactionScope tran = new TransactionScope( TransactionScopeOption.Required, new TransactionOptions(){ IsolationLevel= System.Transactions.IsolationLevel.ReadCommitted, Timeout=TimeSpan.FromHours( timeout_in_hours )}, EnterpriseServicesInteropOption.Automatic ))
{
    int total_records_processed = 0;
    foreach (DataRow datarow in data.Rows)
    {
        //Code runs some commands on the DataContext (db),
        //possibly reading/writing records and calling db.SubmitChanges

        total_records_processed++;
        try
        {
            db.SubmitChanges();
        }
        catch (Exception err)
        {
            MessageBox.Show( err.Message );
        }
    }
    tran.Complete();
    return total_records_processed;
}

While the above code is running, it successfully completes 6 or 7 hundred loop iterations. However, after 10 to 20 minutes, the catch block above catches the following error:

{"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."}

The tran.Complete call is never made, so why is it saying the transaction associated with the connection is completed?

Why, after successfully submitting hundreds of changes, does the connection associated with the DataContext suddenly enter a closed state? (That's the other error I sometimes get here).

When profiling SQL Server, there are just a lot of consecutive selects and inserts with really nothing else while its running. The very last thing the profiler catches is a sudden "Audit Logout", which I'm not sure if that's the cause of the problem or a side-effect of it.

Triynko
  • 18,766
  • 21
  • 107
  • 173

1 Answers1

1

Wow, the max timeout is limited by machine.config: http://forums.asp.net/t/1587009.aspx/1

"OK, we resolved this issue. apparently the .net 4.0 framework doesn't allow you to set your transactionscope timeouts in the code as we have done in the past. we had to make the machine.config changes by adding

< system.transactions> < machineSettings maxTimeout="02:00:00"/>
< defaultSettings timeout="02:00:00"/> < /system.transactions>

to the machine.config file. using the 2.0 framework we did not have to make these entries as our code was overriding teh default value to begin with."

It seems that the timeout you set in TransactionScope's constructor is ignored or defeated by a maximum timeout setting in the machine.config file. There is no mention of this in the documentation for the TransactionScope's constructor that accepts a time out parameter: http://msdn.microsoft.com/en-us/library/9wykw3s2.aspx

This makes me wonder, what if this was a shared hosting environment I was dealing with, where I could not access the machine.config file? There's really no way to break up the transaction, since it involves creating data in multiple tables with relationships and identity columns whose values are auto-incremented. What a poor design decision. If this was meant to protect servers with shared hosting, it's pointless, because such a long-running transaction would be isolated to my own database only. Also, if a program specifies a longer timeout, then it obviously expects a transaction to take a longer amount of time, so it should be allowed. This limitation is just a pointless handicap IMO that's going to cause problems. See also: TransactionScope maximumTimeout

Community
  • 1
  • 1
Triynko
  • 18,766
  • 21
  • 107
  • 173