EntityFramework中的TransactionScope TransactionInDoubtException

时间:2014-11-09 15:02:25

标签: c# asp.net entity-framework entity-framework-6 transactionscope

以下代码是我的业务层的一部分:

   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;
                }

            }
        }
    }

有时候(每周一次或两次)我得到TransactionInDoubtException。 Stacktrace:

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

据我所知,默认的隔离级别是可序列化的,因此这个原子操作应该没有问题。 (假设由于写锁定而没有超时)

如何解决问题?

4 个答案:

答案 0 :(得分:4)

使用transaction.Rollback而不是transaction.Dispose

如果事务处于挂起状态,则始终在异常时回滚。

答案 1 :(得分:0)

msdn说"如果事务管理器在发送单阶段提交请求之后但在收到结果通知之前失去与下级参与者的联系,则它没有可靠的机制来恢复事务的实际结果。因此,交易经理向等待信息结果通知的任何申请或选民发送In Inouboub结果"

请查看这些链接

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 :(得分:0)

添加finally块以处理事务。如果提交事务,请设置一些status = true。

在finally块中检查相同,如果status为true,则不要回滚,否则回滚并处理该事务。

答案 3 :(得分:0)

如果您将try / catch移动到包含Transaction范围的using指令,它会表现得正常吗? using指令应该隐式为你调用Dispose(这样做显然看起来多余)然后你可以抛出异常。这就是我在MSDN的示例中看到的实现:

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