遇到TransactionInDoubtException时是否发生部分提交?

时间:2014-04-30 07:36:00

标签: c# sql-server sql-server-2008 msdtc

遇到TransactionInDoubtException时会发生部分提交吗?如果是这样,如何回滚提交/正确处理TransactionInDoubtException

var option = new TransactionOptions();
option.IsolationLevel = IsolationLevel.ReadCommitted
using (var scope = new TransactionScope(TransactionScopeOption.Required, option))
{
    try
    {
         Context.SaveEmail(_emailInfoList);
         context.SaveSyncState(syncState);
         scope.Complete();
         return true;
    }
    catch (TransactionInDoubtException ex)
    {
         // Looks like commit has already taken place 
         // How to roll back the changes ??
         // sth like scope.Rollback()
    }
}

1 个答案:

答案 0 :(得分:0)

根据 MSDN

  

尝试对事务执行操作时抛出此异常   这是有疑问的。当交易的状态时,交易是有疑问的   交易无法确定。具体来说,的最终结果   这项交易,无论是承诺还是中止,都是不可知的   事务。

     

尝试提交时也会抛出此异常   交易和交易变得毫无疑问。

     

这是一个可恢复的错误。

修改

恢复: 你必须抓住TransactionInDoubtException&用适当的检查写补偿逻辑。

using (var scope = new TransactionScope(TransactionScopeOption.Required, option))
    {
        try
        {
            Context.SaveEmail(_emailInfoList);
            context.SaveSyncState(syncState);
            scope.Complete();
            return true;
        }
        catch (TransactionInDoubtException ex)
        {
            //check whether any one record from the batch has been partially committed . If committed then no need to reprocess this batch.     

            // transaction scope should be disposed first .

            scope.Dispose();

            if (IsReprocessingNeeded(syncState))
                throw;

            return true;
        }
    }

        /// <returns></returns>
        private bool IsReprocessingNeeded(SyncStateDataModal syncState)
        {
            while (true)
            {
                try
                {
                    var id = _emailInfoList[0].ID;
                    bool isEmailsCommitted = Context.GetJournalEmail().FirstOrDefault(a => a.ID == id) != null;
                    if (!isEmailsCommitted)
                        return true;
                    if (context.EmailSynch(syncState.Id) == null)
                    {
                        context.SaveSyncState(syncState);
                    }
                    return false;
                }
                catch (Exception ex)
                {

                    Thread.Sleep(TimeSpan.FromMinutes(AppConfiguration.RetryConnectionIntervalInMin));
                }
            }
        }

消息来源 What is the recovery path for TransactionInDoubtException ?