WS トランザクション フロー

Download sample

このサンプルでは、クライアントによって調整されるトランザクションの使用方法と、WS-AtomicTransaction プロトコルまたは OleTransactions プロトコルを使用するトランザクション フローに関するクライアントとサーバーのオプションの使用方法を示します。このサンプルは、電卓サービスを実装する「入門サンプル」に基づいていますが、これらの操作は、どの程度のトランザクション フローが可能かを TransactionFlowAttribute および TransactionFlowOption 列挙体を使用して設定する方法を示すためのものです。フローされたトランザクションのスコープ内では、要求された操作のログがデータベースに書き込まれ、クライアント調整トランザクションが完了するまで保持されます。クライアント トランザクションが完了しない場合は、データベースに対する該当する更新はコミットされません。

Noteメモ :

このサンプルのセットアップ手順とビルド手順については、このトピックの最後を参照してください。

サービスとトランザクションへの接続を開始した後で、クライアントは複数のサービス操作にアクセスします。サービスのコントラクトは次のとおりに定義されています。操作はそれぞれ、TransactionFlowOption の設定が異なります。

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Mandatory)]
    double Add(double n1, double n2);
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Allowed)]
    double Subtract(double n1, double n2);
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.NotAllowed)]
    double Multiply(double n1, double n2);
    [OperationContract]
    double Divide(double n1, double n2); 
}

操作は、処理される順に次のように定義されています。

  • Add (加算) 操作要求には、フローされたトランザクションが含まれている必要があります。

  • Subtract (減算) 操作要求には、フローされたトランザクションが含まれていてもかまいません。

  • Multiply (乗算) 操作要求では、フローされたトランザクションが含まれてはならないことが、明示的な NotAllowed 設定で指定されています。

  • Divide (除算) 操作要求では、フローされたトランザクションが含まれていてはならないことが、TransactionFlow 属性の省略によって指定されています。

トランザクション フローを有効にするには、適切な操作の属性に加えて、使用するバインディングで transactionFlow プロパティが有効化されている必要があります。このサンプルでは、サービスの構成は Metadata Exchange エンドポイントのほかに TCP エンドポイントと HTTP エンドポイントを公開します。TCP エンドポイントと HTTP エンドポイントは、次のバインディングを使用します。どちらのバインディングでも transactionFlow プロパティは有効化されています。

<bindings>
  <netTcpBinding>
    <binding name="transactionalOleTransactionsTcpBinding"
             transactionFlow="true"
             transactionProtocol="OleTransactions"/>
  </netTcpBinding>
  <wsHttpBinding>
    <binding name="transactionalWsatHttpBinding"
             transactionFlow="true" />
  </wsHttpBinding>
</bindings>
Noteメモ :

システムで提供される netTcpBinding では transactionProtocol を指定できるのに対し、システムで提供される wsHttpBinding では、相互運用性に優れた WSAtomicTransactionOctober2004 プロトコルのみが使用されます。OleTransactions プロトコルは、Windows Communication Foundation (WCF) クライアントで使用する場合にのみ利用できます。

ICalculator インターフェイスを実装するクラスでは、すべてのメソッドの属性で TransactionScopeRequired プロパティが true に設定されています。この設定は、メソッド内で実行されるすべてのアクションがトランザクションのスコープ内で実行されることを宣言するものです。この場合、実行されるアクションには、ログ データベースへの記録が含まれます。操作要求の中に、フローされたトランザクションが含まれている場合は、受信トランザクションのスコープ内でアクションが実行されるか、新しいトランザクションが自動生成されます。

Noteメモ :

TransactionScopeRequired プロパティは、サービス メソッド実装固有の動作を定義しますが、トランザクションをフローさせるためのクライアントの機能や要件は定義しません。

// Service class which implements the service contract.
[ServiceBehavior(TransactionIsolationLevel = System.Transactions.IsolationLevel.Serializable)]
public class CalculatorService : ICalculator
{
    [OperationBehavior(TransactionScopeRequired = true)]
    public double Add(double n1, double n2)
    {
        RecordToLog(String.Format(CultureInfo.CurrentCulture, "Adding {0} to {1}", n1, n2));
        return n1 + n2;
    }

    [OperationBehavior(TransactionScopeRequired = true)]
    public double Subtract(double n1, double n2)
    {
        RecordToLog(String.Format(CultureInfo.CurrentCulture, "Subtracting {0} from {1}", n2, n1));
        return n1 - n2;
    }

    [OperationBehavior(TransactionScopeRequired = true)]
    public double Multiply(double n1, double n2)
    {
        RecordToLog(String.Format(CultureInfo.CurrentCulture, "Multiplying {0} by {1}", n1, n2));
        return n1 * n2;
    }

    [OperationBehavior(TransactionScopeRequired = true)]
    public double Divide(double n1, double n2)
    {
        RecordToLog(String.Format(CultureInfo.CurrentCulture, "Dividing {0} by {1}", n1, n2));
        return n1 / n2;
    }

    // Logging method omitted for brevity
}

クライアントでは、サービスの操作に対する TransactionFlowOption 設定が、クライアントで生成される ICalculator インターフェイスの定義に反映されます。さらに、サービスの transactionFlow プロパティの設定はクライアントのアプリケーション構成に反映されます。クライアントでは、次のように適切な endpointConfigurationName を選択することによってトランスポートとプロトコルを選択できます。

// Create a client using either wsat or oletx endpoint configurations
CalculatorClient client = new CalculatorClient("WSAtomicTransaction_endpoint");
// CalculatorClient client = new CalculatorClient("OleTransactions_endpoint");
Noteメモ :

このサンプルを実行したときの動作は、選択したプロトコルとトランスポートの種類にかかわらず同一です。

サービスへの接続を開始した後で、クライアントは次のように、サービス操作の呼び出しを囲む新しい TransactionScope を作成します。

// Start a transaction scope
using (TransactionScope tx =
            new TransactionScope(TransactionScopeOption.RequiresNew))
{
    Console.WriteLine("Starting transaction");

    // Call the Add service operation
    //  - generatedClient will flow the required active transaction
    double value1 = 100.00D;
    double value2 = 15.99D;
    double result = client.Add(value1, value2);
    Console.WriteLine("  Add({0},{1}) = {2}", value1, value2, result);

    // Call the Subtract service operation
    //  - generatedClient will flow the allowed active transaction
    value1 = 145.00D;
    value2 = 76.54D;
    result = client.Subtract(value1, value2);
    Console.WriteLine("  Subtract({0},{1}) = {2}", value1, value2, result);

    // Start a transaction scope that suppresses the current transaction
    using (TransactionScope txSuppress =
                new TransactionScope(TransactionScopeOption.Suppress))
    {
        // Call the Subtract service operation
        //  - the active transaction is suppressed from the generatedClient
        //    and no transaction will flow
        value1 = 21.05D;
        value2 = 42.16D;
        result = client.Subtract(value1, value2);
        Console.WriteLine("  Subtract({0},{1}) = {2}", value1, value2, result);

        // Complete the suppressed scope
        txSuppress.Complete();
    }

    // Call the Multiply service operation
    // - generatedClient will not flow the active transaction
    value1 = 9.00D;
    value2 = 81.25D;
    result = client.Multiply(value1, value2);
    Console.WriteLine("  Multiply({0},{1}) = {2}", value1, value2, result);

    // Call the Divide service operation.
    // - generatedClient will not flow the active transaction
    value1 = 22.00D;
    value2 = 7.00D;
    result = client.Divide(value1, value2);
    Console.WriteLine("  Divide({0},{1}) = {2}", value1, value2, result);

    // Complete the transaction scope
    Console.WriteLine("  Completing transaction");
    tx.Complete();
}

Console.WriteLine("Transaction committed");

操作の呼び出しは次のとおりです。

  • Add 要求によって、必須のトランザクションがサービスにフローされ、サービスのアクションはクライアントのトランザクション スコープ内で実行されます。

  • 最初の Subtract 要求も、許可されたトランザクションをサービスにフローするので、このときもサービスのアクションはクライアントのトランザクション スコープ内で実行されます。

  • 2 番目の Subtract 要求は、TransactionScopeOption.Suppress オプション付きで宣言された新しいトランザクション スコープ内で実行されます。これによって、クライアントの最初の外側トランザクションが抑制されます。また、新しいトランザクションがサービスにフローされることはありません。この方法を使用すると、クライアントは、トランザクションをサービスにフローすることが必要ない場合に、このことを行わないように明示的に指定できます。サービスのアクションは、新しい独立したトランザクションのスコープ内で発生します。

  • Multiply 要求はトランザクションをサービスにフローしません。クライアントで生成された ICalculator インターフェイスの定義には TransactionFlowOption NotAllowed に設定された TransactionFlowAttribute が含まれているためです。

  • Divide 要求は、トランザクションをサービスにフローしません。同様に、クライアントで生成された ICalculator インターフェイスの定義には TransactionFlowAttribute が含まれていないためです。このときも、サービスのアクションは別の新しい独立したトランザクションのスコープ内で実行されます。

このサンプルを実行すると、操作要求および応答がクライアントのコンソール ウィンドウに表示されます。クライアントをシャットダウンするには、クライアント ウィンドウで Enter キーを押します。

Starting transaction
  Add(100,15.99) = 115.99
  Subtract(145,76.54) = 68.46
  Subtract(21.05,42.16) = -21.11
  Multiply(9,81.25) = 731.25
  Divide(22,7) = 3.14285714285714
  Completing transaction
Transaction committed
Press <ENTER> to terminate client.

サービス操作要求のログ記録は、サービスのコンソール ウィンドウに表示されます。クライアントをシャットダウンするには、クライアント ウィンドウで Enter キーを押します。

Press <ENTER> to terminate the service.
  Writing row to database: Adding 100 to 15.99
  Writing row to database: Subtracting 76.54 from 145
  Writing row to database: Subtracting 42.16 from 21.05
  Writing row to database: Multiplying 9 by 81.25
  Writing row to database: Dividing 22 by 7

実行が正常に終了すると、クライアントのトランザクション スコープが完了し、そのスコープ内で実行されたすべてのアクションがコミットされます。具体的には、ここに示した 5 レコードがサービスのデータベースに保存されます。最初の 2 レコードは、クライアントのトランザクションのスコープ内で発生しています。

クライアントのトランザクション スコープ内の場所で例外が発生した場合は、トランザクションは完了しません。その結果、そのスコープ内でログに記録されたレコードはデータベースにコミットされなくなります。この影響を確認するには、外側のトランザクション スコープを完了させる呼び出しをコメント化した後にサンプルをもう一度実行します。この実行では、最後の 3 つのアクション (2 番目の Subtract 要求、Multiply 要求、Divide 要求) だけがログに記録されます。クライアント トランザクションはこれらのアクションにフローされないからです。

サンプルをセットアップ、ビルド、および実行するには

  1. SQL Server 2005 Express Edition または SQL Server 2005 がインストールされていることを確認してください。サービスの App.config ファイルでは、データベースの connectionString を設定できますが、データベースとの連携を行わない場合は、appSettings usingSql の値を false に設定します。

  2. ソリューションの C# 版または Visual Basic .NET 版をビルドするには、「Windows Communication Foundation サンプルのビルド」の手順に従います。

  3. Windows SDK の WsatConfig.exe ツールを使用して、WCF のトランザクション ネットワーク サポートを有効にします。

  4. 単一コンピュータ構成か複数コンピュータ構成かに応じて、「Windows Communication Foundation サンプルの実行」の手順に従います。

サンプルを複数コンピュータ構成で実行する場合は、Microsoft 分散トランザクション コーディネータ (MSDTC) を構成してネットワーク トランザクション フローを有効にし、WsatConfig.exe ツールを使用して WCF トランザクション ネットワーク サポートを有効にする必要があります。

サンプルを複数コンピュータ構成で実行できるように Microsoft 分散トランザクション コーディネータ (MSDTC) を構成するには

  1. サービス コンピュータで、受信ネットワーク トランザクションを許可するように MSDTC を構成します。

    1. [スタート] ボタンをクリックし、[コントロール パネル]、[管理ツール] の順にポイントして [コンポーネント サービス] をクリックします****。

    2. [マイ コンピュータ] を右クリックし、[プロパティ] をクリックします****。

    3. [MSDTC] タブの [セキュリティの構成] をクリックします****。

    4. [ネットワーク DTC アクセス] および [受信を許可する] のチェック ボックスをオンにします****。

    5. [はい] をクリックして MSDTC サービスを再起動し、[OK] をクリックします****。

    6. [OK] をクリックしてダイアログ ボックスを閉じます。

  2. サービス コンピュータおよびクライアント コンピュータで、Windows ファイアウォールを構成します。例外アプリケーションのリストに、Microsoft 分散トランザクション コーディネータ (MSDTC) を追加します。

    1. Windows ファイアウォール アプリケーションをコントロール パネルから実行します。

    2. [例外] タブの [プログラムの追加] をクリックします****。

    3. フォルダ C:\WINDOWS\System32 に移動します。

    4. Msdtc.exe を選択して、[開く] をクリックします****。

    5. [OK] をクリックして [プログラムの追加] ダイアログ ボックスを閉じ、[OK] をもう一度クリックして Windows ファイアウォール アプレットを閉じます****。

  3. クライアント コンピュータで、送信ネットワーク トランザクションを許可するように MSDTC を構成します。

    1. [スタート] ボタンをクリックし、[コントロール パネル]、[管理ツール] の順にポイントして [コンポーネント サービス] をクリックします****。

    2. [マイ コンピュータ] を右クリックし、[プロパティ] をクリックします****。

    3. [MSDTC] タブの [セキュリティの構成] をクリックします****。

    4. [ネットワーク DTC アクセス] および [送信を許可する] のチェック ボックスをオンにします****。

    5. [はい] をクリックして MS DTC サービスを再起動し、[OK] をクリックします****。

    6. [OK] をクリックしてダイアログ ボックスを閉じます****。

Footer image

Copyright © 2007 by Microsoft Corporation.All rights reserved.