“操作对于交易状态无效”错误和交易范围

问题描述 投票:0回答:10

当我尝试调用包含 SELECT 语句的存储过程时,出现以下错误:

该操作对于交易状态无效

这是我的通话结构:

public void MyAddUpdateMethod()
{

    using (TransactionScope Scope = new TransactionScope(TransactionScopeOption.RequiresNew))
    {
        using(SQLServer Sql = new SQLServer(this.m_connstring))
        {
            //do my first add update statement

            //do my call to the select statement sp
            bool DoesRecordExist = this.SelectStatementCall(id)
        }
    }
}

public bool SelectStatementCall(System.Guid id)
{
    using(SQLServer Sql = new SQLServer(this.m_connstring)) //breaks on this line
    {
        //create parameters
        //
    }
}

我在事务中创建与同一数据库的另一个连接是否有问题?

c# .net sql-server transactions transactionscope
10个回答
70
投票

经过一些研究,似乎我无法使用 TransactionScope 块打开到同一数据库的两个连接。我需要修改我的代码,如下所示:

public void MyAddUpdateMethod()
{
    using (TransactionScope Scope = new TransactionScope(TransactionScopeOption.RequiresNew))
    {
        using(SQLServer Sql = new SQLServer(this.m_connstring))
        {
            //do my first add update statement            
        }

        //removed the method call from the first sql server using statement
        bool DoesRecordExist = this.SelectStatementCall(id)
    }
}

public bool SelectStatementCall(System.Guid id)
{
    using(SQLServer Sql = new SQLServer(this.m_connstring))
    {
        //create parameters
    }
}

18
投票

当我遇到这个异常时,出现了一个InnerException“事务超时”。由于这是在调试会话期间,当我在 TransactionScope 内暂停代码一段时间时,我选择忽略这个问题。

当已部署的代码中出现此特定超时异常时,我认为 .config 文件中的以下部分将帮助您:

<system.transactions> 
        <machineSettings maxTimeout="00:05:00" /> 
</system.transactions>

14
投票

我也遇到了同样的问题,我将事务超时更改为 15 分钟并且有效。 我希望这有帮助。

TransactionOptions options = new TransactionOptions();
options.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
options.Timeout = new TimeSpan(0, 15, 0);
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required,options))
{
    sp1();
    sp2();
    ...

}

8
投票

对于未来遇到这种情况的任何流浪者。如果您的应用程序和数据库位于不同的计算机上,并且您收到上述错误(尤其是在使用 TransactionScope 时),请启用网络 DTC 访问。执行此操作的步骤是:

  1. 添加防火墙规则以允许您的机器相互通信。
  2. 确保分布式事务协调器服务正在运行
  3. 启用网络 dtc 访问。运行 dcomcnfg。转至组件服务 > 我的电脑 > 分布式事务协调器 > 本地 DTC。右键单击属性。
  4. 启用网络 dtc 访问,如图所示。

重要:请勿编辑/更改 DTC 登录帐户字段中的用户帐户和密码,保持原样,否则您将最终重新安装 Windows。


5
投票

当我的事务嵌套在另一个事务中时,我遇到了此错误。是否有可能存储过程声明自己的事务或者调用函数声明一个事务?


3
投票

对我来说,当我在另一个事务块内遇到异常后尝试回滚事务块时,会出现此错误。

我所要做的就是删除我的内部交易块来修复它。

使用嵌套事务时,事情可能会变得非常混乱,最好避免这种情况,只需重构代码即可。


3
投票

就我而言,解决方案既不是增加“transactionscope”的时间,也不是增加 machine.config 文件的“system.transactions”的“machineSettings”属性的时间。

在这种情况下,有一些奇怪的事情,因为这个错误只发生在信息量非常大的时候。

所以问题是基于这样一个事实:在事务内部的代码中,有许多“foreach”对不同的表进行更新(我不得不在其他人员开发的代码中解决这个问题)。如果测试时表中记录很少,则不会显示错误,但如果记录数增加,则会显示错误。

最终的解决方案是从单个事务更改为事务内不同“foreach”中的多个单独事务。


0
投票

您不能同时打开两笔交易。我所做的是在返回第二个事务将使用的结果之前指定 transaction.Complete() ;)


0
投票

我更新了一些处理部分数据库进程的专有第三方库,并在所有保存调用中收到此错误。我必须更改 web.config 事务密钥部分中的值,因为(事实证明)引用的事务范围方法已从一个库移至另一个库。

之前还有其他错误与该密钥相关,但我通过注释掉该密钥来消除它们(我知道我当时应该持怀疑态度,但我认为它现在是多余的,因为它不在闪亮的新版本中)图书馆)。


0
投票

对于登陆此页面的任何人,这里有另一个可能的原因:留意异步数据库调用。

这行不通:

//pseudocode
using (new TransactionScope(whatever))
{
    await QueryDatabase();
    //"await" frees up the thread, it goes back into the pool
    //and if other code calls the database again
    //on the freed-up thread, it will fail
}
© www.soinside.com 2019 - 2024. All rights reserved.