ASP.NET中TransactionScope存在的问题

5
我已经建立了一个类来同步两个不同数据源之间的数据。这个同步分为多个部分(和方法)。每个方法都有自己的TransactionScope,这些方法按顺序运行。
每次我运行这段代码时,我都会收到以下错误消息:
"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."
下面的代码是一个带有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;
        }
}

看起来调用"_transactionScope.Complete()"并不能足以终止事务范围.. 有没有人知道我做错了什么?

提前感谢!

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

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

1
你的交易持续时间超过10分钟了吗? - Bongo Sharp
我认为有一些交易持续时间超过10分钟,但我通过设置'transactionOptions.Timeout'属性和SqlCommand.CommandTimeout属性为1小时来处理它们。 - user740229
1
如果事务运行的时间超过了maxTimeout,就会出现此错误。请查看此博客文章:http://thecodesaysitall.blogspot.se/2012/04/long-running-systemtransactions.html 或者此答案:https://dev59.com/N3E85IYBdhLWcg3wJQAa#10017056。 - Marcus
只是一个技术提示...不要使用"throw e",而是只使用"throw"。这样可以保留调用堆栈。 - Sprague
2个回答

5
尝试更改构造函数。
using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required,
                new TransactionOptions()
                { 
                    IsolationLevel = System.Transactions.IsolationLevel.Serializable,
                    Timeout = TimeSpan.FromSeconds(120)
                }))

3

我为事务范围创建了一个最大超时值的方法。

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

然后你会使用它:

using (TransactionScope transaction = TransactionHelper.CreateDefaultTransactionScope())

也可以查看这个链接:http://social.msdn.microsoft.com/forums/en-US/windowstransactionsprogramming/thread/250b40b9-0838-4142-a8ff-d9d26690083b/ - Bongo Sharp

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