citronas
citronas

Reputation: 19375

TransactionScope TransactionInDoubtException in EntityFramework

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?

Upvotes: 3

Views: 1869

Answers (4)

daniel_sweetser
daniel_sweetser

Reputation: 391

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

Upvotes: -1

Dharm Rajodiya
Dharm Rajodiya

Reputation: 9

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.

Upvotes: -1

Techie
Techie

Reputation: 11

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

Upvotes: 0

Azhar Khorasany
Azhar Khorasany

Reputation: 2709

Use transaction.Rollback instead of transaction.Dispose

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

Upvotes: 4

Related Questions