【问题标题】:Error - The transaction associated with the current connection has completed but has not been disposed错误 - 与当前连接关联的事务已完成但尚未处理
【发布时间】:2012-07-12 13:38:04
【问题描述】:

我在使用TransactionScope 将多个数据库查询包装到一个事务中时遇到了问题,我正在使用批处理大小为 500 的 SqlBulkCopy。当我将批处理大小增加到 1000 时,我收到了错误:

与当前连接相关的事务已经完成 但尚未处置。交易必须在 连接可用于执行 SQL 语句。

这是我正在使用的代码:

using (var scope = new TransactionScope())
{
    using (var connection = (SqlConnection)customerTable.OpenConnection())
    {
        var table1BulkCopy = new SqlBulkCopy(connection)
        {
            BatchSize = BATCH_SIZE,
            DestinationTableName = TableName1
        };

        table1BulkCopy.WriteToServer(table1DataTable);

        var table2BulkCopy = new SqlBulkCopy(connection)
        {
            BatchSize = BATCH_SIZE,
            DestinationTableName = TableName2
        };

        table2BulkCopy.WriteToServer(table2DataTable);

        var table3BulkCopy = new SqlBulkCopy(connection)
        {
            BatchSize = BATCH_SIZE,
            DestinationTableName = TableName3
        };

        table1BulkCopy.WriteToServer(table3DataTable);

        var table4BulkCopy = new SqlBulkCopy(connection)
        {
            BatchSize = BATCH_SIZE,
            DestinationTableName = TableName4
        };

        table4BulkCopy.WriteToServer(table4DataTable);

        scope.Complete();
    }
}

【问题讨论】:

    标签: c# .net sql-server-2008 c#-4.0


    【解决方案1】:

    这可能在事务超时时发生。您可以像这样增加事务的超时时间(使用适合预期事务长度的值)。下面的代码是15分钟:

    using (TransactionScope scope = 
                 new TransactionScope(TransactionScopeOption.Required, 
                                       new System.TimeSpan(0, 15, 0)))
      {
          // working code here
      }
    

    这就是为什么它适用于 500 而不是 1000 的原因。

    【讨论】:

    • 我是通过Timeout = TransactionManger.MaximumTimeout 得到的,所以这不是发生此错误的唯一方式。
    • 这个答案解决了我遇到的一个问题。正如@Eric J 提到的,这不是发生此错误的唯一方式,但如果您的事务超时,您确实会收到上面相当不相关的消息。
    • @Pradeep 这是正确答案,应该这样标记。
    • 很棒的解释,很有帮助
    • 这解决了我的问题,原来是操作过于严重,并且在块中完成所有保存/更新操作之前事务已过期...
    【解决方案2】:

    我发现在 TransactionScope 中设置超时对我不起作用。我还需要将以下配置键添加到 end of machine.config <configuration> 标记以延长默认的最大超时 10 分钟。

    <system.transactions>
        <machineSettings maxTimeout="00:30:00" /> <!-- 30 minutes -->
    </system.transactions>
    

    信用: http://thecodesaysitall.blogspot.com.au/2012/04/long-running-systemtransactions.html

    【讨论】:

    • 请注意,您必须将其放在配置部分的末尾,否则您将收到来自 IIS 的错误。
    • 如果我正确阅读了MaxTimeoutdefaultSettings timeout 上的文档,未更改的machine.config 使用没有 TransactionOptions 会产生 1 分钟的超时(并且您可以使用 TransactionOptions 增加到 10 )
    【解决方案3】:

    scope.Complete(); 移出connection 块。

    using (var scope = new TransactionScope())
    {
      using (var connection = (SqlConnection)customerTable.OpenConnection())
       {
        //
       }
      scope.Complete();
    }
    

    【讨论】:

    • 这里有更多信息为什么?将调用放在 using 块中的最后一条语句是非常好的做法。 More info about the method
    【解决方案4】:

    超时问题很明显,但是如果将 TransactionOptions.Timeout 设置得更高,则不会生效。 即使您设置了 TimeSpan.MaxValue,您实际上也不会获得利润。将 TransactionOptions 的 Timeout 属性设置为更高的值无关紧要,TransactionOptions.Timeout 不能超过 maxTimeout 属性。 您应该在 ma​​chine.config 中进行一些更改。

    很快你就会找到 machine.config 文件 %windir%\Microsoft.NET\Framework\你的版本\config\machine.config
    并将其添加到&lt;configuration&gt; 标签中:

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

    您可以在此处将 maxTimeout 属性设置为 30 分钟。
    更多详情请看以下http://thecodesaysitall.blogspot.com/2012/04/long-running-systemtransactions.html

    【讨论】:

      【解决方案5】:

      完整的答案必须更完整。

      您必须在 .Net 代码或服务器配置中指定 - 在哪里确定最大事务超时时间

      <sectionGroup name="system.transactions".... 
          ...allowDefinition="MachineOnly"
      </sectionGroup>
      

      在这种情况下,您可以在 machine.config 中设置最大超时时间

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

      或者您可能想在应用程序中覆盖此行为。然后 在 machine.config 你应该设置属性 velue:

      ...allowDefinition="MachineToApplication"
      

      这是一篇好文章:https://blogs.msdn.microsoft.com/ajit/2008/06/18/override-the-system-transactions-default-timeout-of-10-minutes-in-the-code/

      【讨论】:

        【解决方案6】:

        应用这个:

        TransactionScope(TransactionScopeOption.Required, new System.TimeSpan(0, 30, 0));
        (0, 30, 0) = (hour,minute,seconds)
        

        如果你想测试,用这个 (0, 0, 1) 应用时间跨度,试试你会得到错误。之后,增加秒或分钟或小时并尝试。它会起作用的。

        【讨论】:

          【解决方案7】:

          C# 9 朗版本。 TransactionScopeOption.Suppress 对我来说就像魔术一样。

          // TransactionScopeOption.Suppress works and fixed my issue
          using TransactionScope Scope = new TransactionScope(TransactionScopeOption.Suppress);
          try
          {
              using var CentralConnection = SQLConnection("Other connection string here");
              using var LocalConnection = SQLConnection("Other connection string here");
          
              // Central
              using var cmd0 = new SqlCommand("OtherSQLCommandTextHere", CentralConnection)
              {
                   CommandTimeout = 0 // I just add zero timeout here
              };
              cmd0.ExecuteNonQuery();
          
              // Local
              using var cmd1 = new SqlCommand("OtherSQLCommandTextHere", LocalConnection)
              {
                   CommandTimeout = 0 // I just add zero timeout here
              };
              cmd1.ExecuteNonQuery();
          
              // The Complete method commits the transaction. If an exception has been thrown,
              // Complete is not called and the transaction is rolled back.
              Scope.Complete();
          }
          catch (Exception ex)
          {
              Scope.Dispose();
              MessageBox.Show(ex.ToString());
          }
          
          public SqlConnection SQLConnection(string ISQLConnection)
          {
               SqlConnection conn = null;
               try
               {
                   conn = new SqlConnection(ISQLConnection);
                   conn.Open();            
               }
               catch 
               {
                   // skipping here error message
               }
               return conn;
           }
          

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-07-22
          • 2013-09-17
          相关资源
          最近更新 更多