1

「分散トランザクションが完了しました。このセッションをNULLトランザクションの新しいトランザクションに参加させる」というエラーは、多くの議論とさまざまな原因を伴う広範な問題のようですが、周りを見回しても、原因を特定できません。私の場合はそれです。LINQ-to-SQL DataContextから派生したクラスを使用してデータベースをクエリおよび更新していますが、更新の約半分は、直接SQL更新と、Insert、Update、およびDeleteの部分的なメソッドで別のAPIを介して実行される更新に分割されます。 DataContext。SQLとサードパーティの両方の更新が発生することを検出したら、「TransactionScopeOption.Required」オプションを使用して新しいTransactionScopeオブジェクトを作成し、アンビエントトランザクションを取得して、サードパーティのAPIを同じ分散トランザクションに参加させます。

ほとんどの場合、これは比較的確実に機能しているようです。ただし、まれに再現が難しいエラーが発生することがあります。DataContextの部分的なメソッドで検証に失敗したためにSubmitChanges中に予期される(ユーザー)エラーが発生した場合、コードはCompleteを呼び出さずにTransactionScopeを破棄し、ユーザーにエラーを報告します。同じトランザクションを再試行すると、機能する場合もありますが、エラーが報告され予期しないDTCエラーが発生する場合もあります。

本当に奇妙な部分は、Debug.WriteLineを実行してSystem.Transactions.Transaction.Currentの状態を確認すると、エラーを再現できなくなることです。デバッグストリームではなくテキストファイルに同じ情報を報告するようにコードを変更すると、エラーを簡単に再現できます。奇妙なスレッド同期の問題が発生しているのではないかと思います。

答えを探しているときに、TransactionScopeOptionとしてRequiredではなくRequiresNewを使用しようとする1つのトピックに出くわしました。ただし、これにより、同様の状況で別のエラーが発生しました。「ExecuteReaderには、開いていて使用可能な接続が必要です。接続の現在の状態はOpenです。」

DataContextでRefreshを呼び出すと、(ファイルへのデバッグ出力を介して)アンビエントトランザクションがNothingであることを確認しました。その後、フレームワークのRefreshの実装のどこかで、両方の場合にエラーが発生します。私は困惑しています。なぜ私が取引に参加しようとしていると思うのですか?

編集:パズルはさらに混乱し続けています。同じことをもう一度試しましたが(まだRequiresNewを使用)、「内部.NetFrameworkデータプロバイダーエラー12」が発生しました。ここで何が起こっているのかについての手がかりを与えるかもしれないこのエラー12に関する情報はありますか?

4

1 に答える 1

0

これInternal .Net Framework Data Provider Error 12は、スレッドセーフではないデータフレームワークへのマルチスレッドアクセスが発生していることを示す良い手がかりです。DataContext.Refresh実際、イベントが別のスレッドで発生すると同時に、あるスレッドで実行されていることを確認できましたSystem.Transactions.Transaction.TransactionCompleted。また、トランザクションの他のメンバー(サードパーティAPI)の参加を解除するイベントハンドラーコードがありました。どうやらそれを同時に行おうとすると、私には完全には理解できない混乱が生じましたが、2つのスレッドが接続/トランザクションと同時に対話できないようにすることで簡単に回避できます。SyncLock(VB.NET)、lock(C#)、またはThreading.Monitor.Enterを使用Threading.Monitor.Exitして、複数のスレッドが同時にデータプロバイダーにアクセスしないようにすることをお勧めします。

于 2012-11-15T16:33:36.280 に答える