TransactionScope TransactionInDoubtException in EntityFramework

1.7k views Asked by At

The following code is part of my business layer:

   public void IncrementHits(int ID)
    {
        using (var context = new MyEntities())
        {
            using (TransactionScope transaction = new TransactionScope())
            {
                Models.User userItem = context.User.First(x => x.IDUser == ID);
                userItem.Hits++;
                try
                {
                    context.SaveChanges();
                    transaction.Complete();
                }
                catch (Exception ex)
                {
                    transaction.Dispose();
                    throw;
                }

            }
        }
    }

Sometimes (once or twice a week) I get a TransactionInDoubtException. Stacktrace:

at System.Transactions.TransactionStateInDoubt.EndCommit(InternalTransaction tx) 
at System.Transactions.CommittableTransaction.Commit() 
at System.Transactions.TransactionScope.InternalDispose() 
at System.Transactions.TransactionScope.Dispose() 

As far as I know, the default isolation level is serializable, so there should be no problem with this atomic operation. (Assuming there is no timeout occuring because of a write lock)

How can I fix my problem?

4

There are 4 answers

0
Techie On

msdn says "if the transaction manager loses contact with the subordinate participant after sending the Single-Phase Commit request but before receiving an outcome notification, it has no reliable mechanism for recovering the actual outcome of the transaction. Consequently, the transaction manager sends an In Doubt outcome to any applications or voters awaiting informational outcome notification"

Please look into these links

https://msdn.microsoft.com/en-us/library/cc229955.aspx

https://msdn.microsoft.com/en-us/library/system.transactions.ienlistmentnotification.indoubt(v=vs.85).aspx

2
Azhar Khorasany On

Use transaction.Rollback instead of transaction.Dispose

If you have a transaction in a pending state always rollback on exception.

0
Dharm Rajodiya On

Add finally block to dispose the transaction. And set some status = true if you commit the transactions.

Check same in finally block and if status is true then don't rollback otherwise rollback and dispose the transaction.

0
daniel_sweetser On

Would it behave properly if you moved your try/catch to include the using directive for the Transaction scope? The using directive should implicitly call Dispose for you (so doing it explicitly seems redundant) and then you can throw the exception. This is what I see implement in examples from MSDN:

https://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.dispose(v=vs.110).aspx