60

我已经为此工作了大约一天半,并在网络上搜索了大量的博客和帮助文章。我在 SO 上发现了几个与此错误相关的问题,但我认为它们并不完全适用于我的情况(或者在某些情况下,不幸的是,我无法很好地理解它们以实现:P)。我不确定我能否很好地描述这一点以获得帮助......但这里是:

我们有一个 .NET 应用程序来跟踪我们的资源。具有将资源复制到时间跟踪系统和计费系统的导出功能;这将访问链接到时间和计费数据库的存储过程。

我最近将计费系统数据库移至新服务器(原始服务器:Server 2003 SP2、SQL 2005;新服务器:Server 2008 R2、SQL 2008 R2)。我设置了一个指向 2008 数据库的链接服务器。我更新了存储过程以指向 2008 服务器,然后我收到有关 MSDTC 和 RPC 的错误 (http://www.safnet.com/writing/tech/archives/2007/06/server_myserver.html)。我在链接服务器上启用了“rpc/rpc out”并将 MSDTC 设置为允许网络访问(如下所示:http ://www.sqlwebpedia.com/content/msdtc-troubleshooting )。

现在,当我尝试运行导出功能时,我得到了上述信息:“此 SqlTransaction 已完成;它不再可用。” 对我来说奇怪的是,当我刚刚运行存储过程(来自 SSMS)时,它说它成功完成。

有没有人见过这个?我错过了配置中的某些内容吗?我继续浏览相同的页面,我发现的唯一一件事是在进行 MSDTC 更改后我没有重新启动(在此处提到:http ://social.msdn.microsoft.com/forums/en-US/adodotnetdataproviders /thread/7172223f-acbe-4472-8cdf-feec80fd2e64/)。

我可以发布部分或全部存储过程,如果有帮助...请告诉我。

4

10 回答 10

51

我相信此错误消息是由于“僵尸交易”造成的。

寻找事务被提交两次(或回滚两次,或回滚并提交等)的可能区域。.Net 代码是否在 SP 已经提交事务之后提交事务?.Net 代码是否会在遇到错误时将其回滚,然后尝试在 catch(或 finally)子句中再次回滚?

有可能在旧服务器上从未遇到过错误条件,因此从未遇到过错误的“双重回滚”代码。也许现在您的情况是新服务器上存在一些配置错误,而现在错误代码正在通过异常处理受到影响。

你能调试到错误代码吗?你有堆栈跟踪吗?

于 2011-06-15T14:13:28.033 回答
9

我最近在重构一个新的连接管理器后遇到了这个问题。一个新例程接受了一个事务,因此它可以作为批处理的一部分运行,问题在于 using 块:

public IEnumerable<T> Query<T>(IDbTransaction transaction, string command, dynamic param = null)
{
  using (transaction.Connection)
  {
    using (transaction)
    {
      return transaction.Connection.Query<T>(command, new DynamicParameters(param), transaction, commandType: CommandType.StoredProcedure);
    }
  }
}

看起来好像外部使用正在关闭底层连接,因此任何提交或回滚事务的尝试都会抛出消息"This SqlTransaction has completed; it is no longer usable."

我删除了 usings 添加了一个覆盖测试,问题就消失了。

public IEnumerable<T> Query<T>(IDbTransaction transaction, string command, dynamic param = null)
{
  return transaction.Connection.Query<T>(command, new DynamicParameters(param), transaction, commandType: CommandType.StoredProcedure);
}

在事务的上下文中检查任何可能正在关闭连接的东西。

于 2014-07-13T07:58:51.710 回答
9

有完全相同的问题,只是找不到正确的解决方案。希望这可以帮助某人。

我有一个带有 EF Core 的 .NET Core 3.1 WebApi。在同时收到多个调用时,应用程序试图同时向数据库添加和保存更改。

就我而言,问题在于将保存数据的表没有设置主键。

从模型中的 ID 应该是主键的应用程序运行迁移时,EF Core 以某种方式错过了。

我通过打开 SQL Profiler 并看到所有事务已成功提交到数据库(从应用程序)发现了问题,但只创建了一个新行。探查器还显示某种类型的死锁正在发生,但我在探查器的跟踪日志中看不到更多。在进一步检查中,我注意到“Id”列上缺少主键标识符。

我从我的申请中得到的例外是:

此 SqlTransaction 已完成;它不再可用。

和/或

引发了一个异常,可能是由于暂时性故障。考虑通过将“EnableRetryOnFailure()”添加到“UseSqlServer”调用来启用瞬时错误恢复能力。

于 2020-07-08T13:41:43.420 回答
7

我也有同样的问题。发生此错误是因为连接池。当存在两个或多个用户访问系统时,连接池也重用连接和事务。如果第一个用户执行提交或回滚,则事务不再可用。

于 2015-08-21T14:28:09.760 回答
5

我最近遇到过类似的情况。要在任何 VS IDE 版本中进行调试,请从 Debug(Ctrl + D、E)打开异常 - 选中“Thrown”列的所有复选框,然后在调试模式下运行应用程序。我意识到其中一个表没有正确导入到新数据库中,因此内部 Sql Exception 正在终止连接,从而导致此错误。

故事的要点是,如果以前的工作代码在新数据库上返回此错误,这可能是数据库模式丢失问题,通过上述调试技巧实现,

希望它有帮助,HydTechie

于 2013-05-15T14:18:36.943 回答
4

还要检查从您的 .NET 应用程序对数据库执行的任何长时间运行的进程。例如,您可能正在调用没有足够时间完成的存储过程或查询,这可能会在您的日志中显示为:

  • 执行超时已过期。在操作完成之前超时时间已过或服务器没有响应。

    • 此 SqlTransaction 已完成;它不再可用。

检查命令超时设置尝试运行跟踪(分析器)并查看数据库端发生了什么......

于 2016-12-29T18:52:13.500 回答
3

在我的情况下,问题是事务中包含的一个查询引发了异常,即使异常被“优雅地”处理,它仍然设法回滚整个事务。

我的伪代码是这样的:

var transaction = connection.BeginTransaction();
for(all the lines in a file)
{
     try{
         InsertLineInTable(); // INSERT statement might fail and throw an exception
     }
     catch {
         // notify the user about the error on line x and continue
     }
}

// Commit and Rollback will fail if one of the queries 
// in InsertLineInTable threw an exception
if(CheckTableForErrors())
{
    transaction.Commit();
}
else
{
    transaction.Rollback();
}
于 2015-02-09T17:04:38.287 回答
1

这是一种检测僵尸交易的方法

SqlTransaction trans = connection.BeginTransaction();

//some db calls here

if (trans.Connection != null) //Detecting zombie transaction
{
  trans.Commit();
}

反编译SqlTransaction类,会看到如下

public SqlConnection Connection
{
  get
  {
    if (this.IsZombied)
      return (SqlConnection) null;
    return this._connection;
  }
}

我注意到如果连接关闭,transOP 将变成僵尸,因此不能Commit。就我而言,这是因为我Commit()在一个finally块内,而连接在try块内。这种安排导致连接被释放并被垃圾收集。解决方案是改为放在块Committry

于 2016-02-10T21:42:32.327 回答
0

对于它的价值,我已经在以前的工作代码上遇到过这个问题。我在触发器中添加了 SELECT 语句以进行调试测试并忘记删除它们。当其他东西输出到“网格”时,实体框架/MVC 不能很好地发挥作用。确保检查任何恶意查询并将其删除。

于 2021-02-24T14:42:37.637 回答
0

就我而言,我有一些代码需要在提交事务后在同一个 try-catch 块中执行。其中一个代码引发了错误,然后 try 块将错误移交给包含事务回滚的 catch 块。它将显示类似的错误。例如,看下面的代码结构:

SqlTransaction trans = null;

try{
 trans = Con.BeginTransaction();
// your codes

  trans.Commit();
//your codes having errors

}
catch(Exception ex)
{
     trans.Rollback(); //transaction roll back
    // error message
}

finally
{ 
    // connection close
}

希望它会帮助某人:)

于 2019-03-06T03:06:04.683 回答