C# SQL分布式事务已完成。要么将此会话加入新事务,要么加入空事务。

4
我在尝试从C#运行SQL Server 2005数据库中的存储过程时,遇到了这个错误(分布式事务已完成。将此会话注册到新事务或NULL事务中)。我没有主动/有意使用任何事务等,这就是这个错误奇怪的原因。我可以从管理工具中运行存储过程并且它可以正常工作。其他存储过程也可以从C#中运行,只有这一个存在问题。错误会立即返回,因此不可能是超时问题。代码大致如下:
  SqlCommand cmd = null;
  try
  {
      // Make sure we are connected to the database
      if (_DBManager.CheckConnection())
      {
        cmd = new SqlCommand();

        lock (_DBManager.SqlConnection)
        {
          cmd.CommandText = "storedproc";
          cmd.CommandType = System.Data.CommandType.StoredProcedure;
          cmd.Connection = _DBManager.SqlConnection;

          cmd.Parameters.AddWithValue("@param", value);

          int affRows = cmd.ExecuteNonQuery();

          ...
        }
      }
      else
      {
        ...
      }
  }
  catch (Exception ex)
  {
    ...
  }

这真让我感到困惑。谢谢您的任何帮助。

2个回答

4
看起来有一个 TransactionScope 不太对劲。 _DBManager.CheckConnection_DBManager.SqlConnection 听起来像是你保持了一个 SqlConnection 状态,我想这会导致问题。
说实话,在大多数情况下,最好只是使用内置的连接池,并在本地使用 using 连接——也就是说,不要保持连接状态。
using(var conn = new SqlConnection(...)) { // or a factory method
    // use it here only
}

在这里,您将获得一个干净的 SqlConnection ,它将通过池映射到非托管连接,即每次不会创建实际连接(但会进行逻辑重置以清理它)。
这也允许更多线程的灵活使用。例如,在Web应用程序中使用静态连接将会导致阻塞,这是可怕的。

我只保留一个连接的原因是因为我要插入大量数据,不想每次都打开连接导致速度变慢。我会尝试这种方法并查看它的速度。但仍然无法解释为什么曾经有效的代码现在不起作用了,即使没有做任何更改。 - mike
哦,同时,在管理工作室的活动监视器中,我可以看到我的连接下有一个“打开事务”。“这意味着存在一项悬而未决的交易。是否有任何方法可以获取有关打开交易的更多详细信息?感谢您的帮助。 - mike
1
已打开的连接通常会在应用程序生命周期内保留在池中;要完全终止它并不容易,除非禁用池,这会牺牲池的性能优势。 - Marc Gravell

0
从代码中看,似乎您正在利用已经打开的连接。可能之前在同一连接上有未完成的事务。

你似乎在这里找到了一些线索。如果我在调用存储过程之前使用.Close()和.Open()关闭并打开连接,那么它就能正常工作。虽然过去没有必要这样做,但是其他使用相同代码(但不同存储过程)的程序仍然可以正常工作。我无法找到程序之间的任何不同之处,除了存储过程名称和参数。我已经在每个查询之后调用了reader.Close(); reader.Dispose(); command.Dispose();(适当的地方)。有没有办法确保事务被关闭? - mike
你可能想要检查存储过程。你是否从中使用了任何事务...或者表上是否有任何触发器默认为事务。 - S M Kamran
在分层架构中,最好在业务逻辑层实现操作的原子性,但是大多数层设计者会在每个数据访问层操作中打开和关闭连接。如果您想解决连接问题,则可以在逻辑层打开连接,然后将其传递给数据访问层。这样,您就可以跟踪使用的连接。顺便说一句,使用单个连接并允许同步访问会严重降低应用程序的性能,我相信这一点。 - S M Kamran
你确定在锁定状态下关闭连接吗?如果你获取了一个锁,并且另一个请求正在等待相同的锁完成,那么连接将会被重新获取一旦锁块完成。所以如果连接没有关闭,那么可能会出现问题。 - S M Kamran
实际存储过程内部没有任何问题。没有触发器,也没有事务。这段代码已经运行了几个月了,不知道是什么原因导致它停止工作。连接已经保持打开状态,以便在程序运行期间加快查询速度。我将尝试使用连接池来看看效果如何。我不太喜欢在逻辑中处理连接的打开/关闭,我更希望由数据访问层(DAL)来处理,这也是目前的工作方式。感谢您的建议。 - mike

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