TransactionScopeRequired=true の WCF サービスで実行している状況があります。これは、常にアンビエント トランザクションが存在することを意味します。
ただし、アプリケーションの存続期間中は新しい接続を開始する必要があります。つまり、abmbient トランザクションを使用することはできません。
これを行う方法についてのアイデアはありますか?これを行うだけで、自動的にアンビエント トランザクションが使用されます。
Assert.IsNotNull(System.Transactions.Transaction.Current);
var conn = new OracleConnection("my connection string");
conn.Open(); // <-- picks up ambient transaction, but I don't want that
実際には、次のようにすると、この例をより簡単にすることができます。
OracleConnection conn; // <-- this is actually held around in another object that has a very long lifetime, well past the TransactionScope.
using(var tx = new TransactionScope())
{
conn = new OracleConnection("my connection string");
conn.Open(); // <-- picks up ambient transaction, but I don't want that
// ... do stuff
}
接続で実際に TransactionScope を取得したくありません。実際のコードでは、スコープ内で DB アクションを実行するためにさらに多くのことが行われています。トランザクション スコープの有効期間を過ぎても維持する必要があるのは 1 つだけです。
本当の状況は言及する価値があると思います。ここで実際に起こっていることは、WCF サービスの呼び出し中に、Enterprise Library Caching ブロックを使用してオブジェクトをキャッシュに追加することです。このオブジェクトはデータ テーブルですが、継続的な通知が設定されている Oracle へのオープン接続も保持します。これにより、基になる Oracle テーブルが変更されたときに、キャッシュされたデータセットを自動的に更新できます。
データ キャッシュ項目には、WCF で初期化された任意の数のスレッドからアクセスできます。これらのスレッドはすべて、独自のトランザクション スコープで実行されます。OracleConnection オブジェクトをキャッシュに入れていると考えることができると思います。テキスト/サンプルコードのより良いブロックは次のようになります:
//beginning of a WCF service call
using (var tx = new TransactionScope())
{
var conn = new OracleConnection();
var cmd = new OracleCommand();
// set up OCN on the cmd and connection
var reader = cmd.ExecuteReader();
cache.Add("conn", conn);
cache.Add("cmd", cmd);
}
//beginning of a second wcf service call
using (var tx = new TransactionScope())
{
var conn = cache.Get("conn");
var cmd = cache.Get("cmd");
var reader = cmd.ExecuteReader();
// user reader to reload some data
}
ポイントは、複数のスレッドとトランザクション スコープにわたって有効期間が長い接続があることです。