尝试创建/使用内部事务时出现异常

时间:2010-12-14 03:01:20

标签: .net linq transactions datacontext

我的应用程序(WCF服务)使用LINQ数据上下文,最近我们决定将所有内容包装在事务中。似乎工作得很好;每次调用服务都有自己的事务,因此如果抛出异常,则回滚所有内容,并且不会对数据库进行任何更改。

但是我们有一个“管理员代码”的概念,它可以生成并仅使用一次。我们希望管理员代码将被标记为正在使用,即使在操作后期发生错误也是如此。对我来说,这表明我应该使用内部交易?

所以在我的SetToUsed方法中,我输入了一个新的事务:

    public void SetToUsed(string code)
    {
        // security codes explicitly need their own transaction so that they will still be marked as having been used even if the outer transaction were to be rolled back due to error
        using (var securityCodeTransaction = new TransactionScope(
                TransactionScopeOption.RequiresNew,
                new TransactionOptions
                {
                    IsolationLevel = IsolationLevel.ReadUncommitted
                },
                EnterpriseServicesInteropOption.Automatic))
        {
            var returnedItems = m_safetyCodeRepository.FindAll(sc => sc.safetyCode == code &&
                                                                     sc.safetyCodeTypeId == (long)GetCodeType() &&
                                                                     sc.isUsed == false);
            foreach (var item in returnedItems)
            {
                item.isUsed = true;
                m_safetyCodeRepository.SaveChanges(item);
            }

            securityCodeTransaction.Complete();
        }
    }

但是,这会导致异常:System.InvalidOperationException: Connection currently has transaction enlisted. Finish current transaction and retry.
FindAll行引发了异常,这是

的瘦包装
dataContext.GetTable<tbSftSafetyCodes>().Where(exp).ToList()

我错过了什么,或者以完全错误的方式解决这个问题?

编辑:我意识到我实际上并不需要一个交易来监督管理员代码本身的变化 所以我将TransactionScopeOption改为TransactionScopeOption.Suppress。我仍然想知道为什么使用TransactionScopeOption.RequiresNew使用内部事务不起作用!

2 个答案:

答案 0 :(得分:4)

TransactionScopeOption.RequiresNew    

尝试启动一个独立于它所在的全新事务,这是你想要的吗? Requires选项将新事务登记到当前活动的事务中。

但是,如果yopu总是希望将代码标记为已使用 - 您是否需要在事务中使用它?您是否可以在开始事务包装操作之前将其标记为已使用的amd commit?

答案 1 :(得分:0)

在我的情况下,除了使用选项TransactionScopeOption.RequiresNew之外,还必须在using语句之前加上

    dc.Connection.Open();
    dc.Connection.EnlistTransaction(Transaction.Current);
    if (dc.Connection.State!=ConnectionState.Closed) dc.Connection.Close();

    using (var securityCodeTransaction = new TransactionScope(
            TransactionScopeOption.RequiresNew,
            new TransactionOptions
            {
                IsolationLevel = IsolationLevel.ReadUncommitted
            },
            EnterpriseServicesInteropOption.Automatic))
    {
            // same code as in question
    }

这使问题消失了 - 但是,我不知道为什么要这样做。

注意:为了登记交易,必须打开连接 - 因此需要打开+关闭语句。