ASP.NET中TransactionScope的问题

时间:2021-01-11 16:38:23

I've build a class to synchronize data between two different datasources. This synchronization is divided into multiple parts (and methods). Every method has his own TransactionScope and the methods are run sequentially.

我已经构建了一个类来同步两个不同数据源之间的数据。此同步分为多个部分(和方法)。每个方法都有自己的TransactionScope,方法按顺序运行。

Everytime I Run this code I get the following errormessage:

每次运行此代码时,我都会收到以下错误消息:

"The transaction associated with the current connection has completed but has not been disposed. The transaction must be disposed before the connection can be used to execute SQL statements."

“与当前连接关联的事务已完成但尚未处理。事务必须在连接可用于执行SQL语句之前处理。”

The following code is an example of such a method with a TransactionScope:

以下代码是使用TransactionScope的此类方法的示例:

private void SomeMethod()
{
        try
        {
            using (var _transactionScope = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
            {
                using (SqlConnection _connection = new SqlConnection(connectionstring))
                {
                    _connection.Open();

                    DoSomething()...
                }

                _transactionScope.Complete();
            }
        }
        catch (TransactionAbortedException e)
        {
            nlog.Error(string.Format("The transaction has been aborted: {0}", e.Message));
            throw e;
        }
        catch (Exception e)
        {
            throw e;
        }
}

It seems that the call "_transactionScope.Complete()" isn't enough to kill the transactionscope.. Does anyone have a clue what i'm doing wrong?

似乎调用“_transactionScope.Complete()”还不足以杀死事务范围。有没有人知道我做错了什么?

Thanks in advance!

提前致谢!

UPDATE Thanks for your replies. After a few tests I discovered that this problem only exists when there are multiple queries in one method. for example:

更新感谢您的回复。经过几次测试后,我发现只有在一个方法中有多个查询时才会出现此问题。例如:

 try
    {
        using (TransactionScope _transactionScope = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
        {
            using (SqlConnection _connection = new SqlConnection(connectionstring))
            {
                _connection.Open();

                //new method:
                using (TransactionScope _transactionScope = new TransactionScope(TransactionScopeOption.Suppress))
                {
                    //a selectquery
                }

                //an update or insert query

            _transactionScope.Complete();
        }
    }

2 个解决方案

#1


5  

Try changing the constructor.

尝试更改构造函数。

using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required,
                new TransactionOptions()
                { 
                    IsolationLevel = System.Transactions.IsolationLevel.Serializable,
                    Timeout = TimeSpan.FromSeconds(120)
                }))

#2


3  

I did a method for creating a Max Timeout value on a transaction scope

我做了一个在事务范围上创建Max Timeout值的方法

public static TransactionScope CreateDefaultTransactionScope(TransactionScopeOption option = TransactionScopeOption.Required)
    {
        var transactionOptions = new TransactionOptions();
        transactionOptions.Timeout = TimeSpan.MaxValue;
        transactionOptions.IsolationLevel = IsolationLevel.ReadCommitted;
        return new TransactionScope(option, transactionOptions);
    }

and then you would use it:

然后你会用它:

using (TransactionScope transaction = TransactionHelper.CreateDefaultTransactionScope())

#1


5  

Try changing the constructor.

尝试更改构造函数。

using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required,
                new TransactionOptions()
                { 
                    IsolationLevel = System.Transactions.IsolationLevel.Serializable,
                    Timeout = TimeSpan.FromSeconds(120)
                }))

#2


3  

I did a method for creating a Max Timeout value on a transaction scope

我做了一个在事务范围上创建Max Timeout值的方法

public static TransactionScope CreateDefaultTransactionScope(TransactionScopeOption option = TransactionScopeOption.Required)
    {
        var transactionOptions = new TransactionOptions();
        transactionOptions.Timeout = TimeSpan.MaxValue;
        transactionOptions.IsolationLevel = IsolationLevel.ReadCommitted;
        return new TransactionScope(option, transactionOptions);
    }

and then you would use it:

然后你会用它:

using (TransactionScope transaction = TransactionHelper.CreateDefaultTransactionScope())