2012-07-12 78 views
46

TransactionScopeを使用して複数のデータベースクエリをトランザクションにラップするのに問題が発生しました。バッチサイズ500のSqlBulkCopyを使用しています。 connectionブロック外エラー - 現在の接続に関連付けられたトランザクションは完了しましたが、処理されませんでした

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(); 
    } 
} 

答えて

7

移動scope.Complete();

The transaction associated with the current connection has completed but has not been disposed. The transaction must be disposed before the connection can be used to execute SQL statements.

これは私が使用しているコードは次のとおりです。サイズは、1000年に私はエラーを取得しています。

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

詳細理由:

...allowDefinition="MachineToApplication" 

これは良いarcticleありますか?呼び出しをusingブロックの最後のステートメントとするのは、非常に良い方法です。 [方法の詳細](https://msdn.microsoft.com/es-es/library/system.transactions.transactionscope.complete(v = vs.110).aspx) – Angel

+1

これは役に立ちました。ありがとうございます –

85

私はこれが遅いと知っていますが、おそらくそれは他の人を助けるでしょう。

これは、トランザクションがタイムアウトすると発生します。このようなトランザクションのタイムアウトを増やすことができます(トランザクションの予想される長さに適した値を使用します)。以下のコードは15分間です:

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

それは私がのTransactionScopeでタイムアウトを設定することは私のために動作しないことがわかっバッチサイズ500用ではなく1000

+0

私は 'Timeout = TransactionManger.MaximumTimeout'でこれを取得しています。だから、このエラーが発生する唯一の方法ではありません。 –

+0

この回答は私が持っていた問題を修正しました。 @Eric Jは、このエラーが発生する唯一の方法ではなく、あなたのトランザクションがタイムアウトした場合には、上記の関係のないメッセージを取得します。 – b0redom

+0

@Pradeepこれは正しい答えであり、そのようにマークする必要があります。 – Kiquenet

17

のために働いている可能性が理由です。また、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

+0

これはconfigセクションの* end *に置く必要があります。そうしないと、IISからエラーが発生します。 –

0

完全な答えはもっといっぱいでなければなりません。最大トランザクションタイムアウトが決定されます - -

あなたが指定する必要があります

.NETコードで、またはこの場合、サーバ設定

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

であなたはのmachine.configで最大タイムアウトを設定することができます

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

また、アプリケーションでこの動作を無効にすることもできます。その後のmachine.configで あなたはatribute velueを設定する必要があります。ここではhttps://blogs.msdn.microsoft.com/ajit/2008/06/18/override-the-system-transactions-default-timeout-of-10-minutes-in-the-code/

関連する問題