错误 - 与当前连接关联的事务已完成但尚未处理

时间:2012-07-12 13:38:04

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

我一直在使用TransactionScope将多个数据库查询包装到事务中时遇到问题,我正在使用带有batchsize 500的SqlBulkCopy。当我将批量大小增加到1000时,我收到错误:< / p>

  

与当前连接关联的事务已完成   但尚未处理。交易必须在交易之前处理   连接可用于执行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();
    }
}

6 个答案:

答案 0 :(得分:107)

当交易超时时会发生这种情况。您可以像这样增加事务的超时(使用适合预期事务长度的值)。以下代码为15分钟:

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

这就是为什么它可以用于batchsize 500而不是1000.

答案 1 :(得分:19)

我发现在TransactionScope中设置超时对我不起作用。我还需要将以下配置密钥添加到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

答案 2 :(得分:7)

scope.Complete();移到connection区块之外。

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

答案 3 :(得分:0)

完整答案必须更加完整。

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

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

在这种情况下,您可以在machine.config

中设置max timeout
<configuration>
 <system.transactions>
 <machineSettings maxTimeout="01:00:00" />
 </system.transactions>
</configuration> 

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

...allowDefinition="MachineToApplication"

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

答案 4 :(得分:0)

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

不久,您应该找到machine.config文件 %windir%\ Microsoft.NET \ Framework \ 您的版本 \ config \ machine.config
并将其添加到<configuration>标签中:

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

您可以在此处将maxTimeout属性设置为30分钟。
有关更多详细信息,请参见以下内容http://thecodesaysitall.blogspot.com/2012/04/long-running-systemtransactions.html

答案 5 :(得分:0)

C#9 Lang版本。 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;
 }