TransactionScope Entity Framework 中的 TransactionInDoubtException问题

3
以下代码是我的业务层的一部分:
   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”异常。堆栈跟踪:
at System.Transactions.TransactionStateInDoubt.EndCommit(InternalTransaction tx) 
at System.Transactions.CommittableTransaction.Commit() 
at System.Transactions.TransactionScope.InternalDispose() 
at System.Transactions.TransactionScope.Dispose() 

据我所知,MySQL的默认隔离级别是可串行化的,因此这个原子操作应该没有问题。(假设没有由于写锁导致的超时问题)
那么我该如何解决我的问题呢?

你至少应该能够重试SaveChanges()调用。 - Gert Arnold
将事务视为具有可空布尔状态的对象(拥有该事务引用的每个人都可以更改该标志)。 如果没有人更改此状态,则保持为空,如果有人调用Commit(),则状态变为true。 如果有人调用Rollback(),则状态变为false。最终,事务将完成,并使用状态确定其结果。 由于您什么也没做,因此状态为null,这就是此时“存疑”交易的内容。只有状态为true的交易最终才会提交。 - Simon Mourier
此外,就目前而言,你的try catch是无用的,因为即使发生异常(这就是using的全部意义),Dispose()也会被执行。 - Simon Mourier
2
据我理解,@GertArnold 的意图是安全地增加 userItem.Hits。为此,OP 将选择(First)和更新(SaveChanges)封装到一个串行化级别的事务中。 - Evk
只是一个小提示:在你的代码中,不要使用try-catch。这正是我们使用“using transactionScope”的原因——它为try-finally提供了语法糖。而这个隐藏的try-finally将负责调用dispose,无论是否发生异常。因此,在这里使用try-catch是多余的。 - Dmitry Gusarov
显示剩余14条评论
4个回答

4

使用transaction.Rollback而不是transaction.Dispose

如果您的事务处于挂起状态,总是在发生异常时回滚。


1
是的,有道理。但你知道我为什么会在第一次出现异常吗?或者这个异常不是我的“真正”异常吗?我很困惑。 - citronas
3
如果您的代码发生异常并且事务仍在进行中,那么您没有优雅地退出事务,而是处于一种未决状态下处理该事务。这就是它说事务状态存在疑虑的原因。请注意,此处不提供解释。 - Azhar Khorasany

0

-1

在事务中添加finally块以进行处理。如果您提交了事务,请将一些状态设置为true。

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


-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接