7

I'm using TransactionScope to do some batch insert and updates. Problem is, I'm getting timeout exceptions on a 30 min long operation even when I set the timeout of the TransactionScope to one hour.

Also after the exception it inserts seemingly random amount of the records of the batch. For example the last operation had 12440 inserts and after the timeout there were 7673 records inserted to the table.

The timeout of the SqlConnection and SqlCommand are both set to int.MaxValue.

What am I doing wrong?

Here's my code:

using (TransactionScope transaction = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromHours(1)))
 {
         try
         {
                using (db = new DB())
                {
                //operations here
                }
         }
         catch (Exception ex)
         {
               throw new Exception("DB Error:\r\n\r\n" + ex.Message);
         }

         transaction.Complete();
} // <--- Exception here: Transaction aborted (Inner exception: Timeout)
dstr
  • 8,362
  • 12
  • 66
  • 106
  • 1
    a bigger (and possibly more important) question is "why does a few ten thousand INSERTS take so long?" – Mitch Wheat May 28 '11 at 05:43
  • Could it be a *Command Timeout* that is occurring (and thus being a red-herring for a *TransactionScope Timeout*)? This would explain the "randomness", and considering the records are inserted so *very* slowly... I see question says set to `MaxValue`, but I have a suspicion... that the problem is not what it seems. –  May 28 '11 at 06:14
  • @Mitch: It's done one bye one on a very slow connection. Hence the one hour timeout limit :) @pst: Insert are done in a loop. Every iteration sets the CommandText and executes. So it's not waiting result of a big SQL, I doubt it's a Command timeout. Also I use a very simple DAL with only SqlConnection and SqlCommand, I don't see anything else timing out. I'd gladly check any other thing you could suggest? – dstr May 28 '11 at 10:04

2 Answers2

8

Is your transaction failing after 10 minutes? If so, you are probably hitting the Transaction Manager Maximum Timeout which is set in the machine.config. If I recall correctly, if you try to set a timeout greater than the maximum value then your setting will be ignored. Try upping the value in machine.config and see if that helps your issue.

In terms of random commits do you set Transaction Binding=Explicit Unbind on your connection string? The default value is Transaction Binding=Implicit Unbind. From MSDN:

Implicit Unbind causes the connection to detach from the transaction when it ends. After detaching, additional requests on the connection are performed in autocommit mode. The System.Transactions.Transaction.Current property is not checked when executing requests while the transaction is active. After the transaction has ended, additional requests are performed in autocommit mode.

Basically, when the transaction times out all inserts up to that point will be rolled back but any additional inserts done using the same connection will be done in autocommit mode where every insert statement will be immediately committed. That does sound similar to the scenario you are seeing (but it's hard to know without seeing the full code/repro).

Randy Levy
  • 22,566
  • 4
  • 68
  • 94
2

I would see if you can utilise the SqlBulkCopy Class. It should be much faster, and might eliminate the need for a long timeout.

Mitch Wheat
  • 295,962
  • 43
  • 465
  • 541