次の方法で共有


ワークフロー サービスとの間のトランザクションのフロー

ワークフロー サービスとクライアントはトランザクションに参加できます。 サービス操作をアンビエント トランザクションの一部にするには、TransactedReceiveScope アクティビティ内にReceive アクティビティを配置します。 TransactedReceiveScope内のSendまたはSendReply アクティビティによって行われた呼び出しも、アンビエント トランザクション内で行われます。 ワークフロー クライアント アプリケーションは、 TransactionScope アクティビティを使用してアンビエント トランザクションを作成し、アンビエント トランザクションを使用してサービス操作を呼び出すことができます。 このトピックでは、トランザクションに参加するワークフロー サービスとワークフロー クライアントを作成する手順について説明します。

Warnung

ワークフロー サービス インスタンスがトランザクション内に読み込まれ、ワークフローに Persist アクティビティが含まれている場合、ワークフロー インスタンスはトランザクションがタイムアウトするまでブロックされます。

Von Bedeutung

TransactedReceiveScopeを使用する場合は常に、すべての受信をTransactedReceiveScopeアクティビティ内のワークフローに配置することをお勧めします。

Von Bedeutung

TransactedReceiveScopeを使用し、メッセージが正しくない順序で到着すると、最初の順序外メッセージを配信しようとするとワークフローが中止されます。 ワークフローがアイドル状態になったときに、ワークフローが常に一貫した停止ポイントにあることを確認する必要があります。 これにより、ワークフローを中止した場合に、以前の永続化ポイントからワークフローを再起動できます。

共有ライブラリを作成する

  1. 新しい空の Visual Studio ソリューションを作成します。

  2. Commonという名前の新しいクラス ライブラリ プロジェクトを追加します。 次のアセンブリへの参照を追加します。

    • System.Activities.dll

    • System.ServiceModel.dll

    • System.ServiceModel.Activities.dll

    • System.Transactions.dll

  3. Common プロジェクトに PrintTransactionInfo という新しいクラスを追加します。 このクラスは NativeActivity から派生し、 Execute メソッドをオーバーロードします。

    using System;  
    using System;  
    using System.Activities;  
    using System.Transactions;  
    
    namespace Common  
    {  
        public class PrintTransactionInfo : NativeActivity  
        {  
            protected override void Execute(NativeActivityContext context)  
            {  
                RuntimeTransactionHandle rth = context.Properties.Find(typeof(RuntimeTransactionHandle).FullName) as RuntimeTransactionHandle;  
    
                if (rth == null)  
                {  
                    Console.WriteLine("There is no ambient RuntimeTransactionHandle");  
                }  
    
                Transaction t = rth.GetCurrentTransaction(context);  
    
                if (t == null)  
                {  
                    Console.WriteLine("There is no ambient transaction");  
                }  
                else  
                {  
                    Console.WriteLine("Transaction: {0} is {1}", t.TransactionInformation.DistributedIdentifier, t.TransactionInformation.Status);  
                }  
            }  
        }  
    
    }  
    

    これは、アンビエント トランザクションに関する情報を表示するネイティブ アクティビティであり、このトピックで使用されるサービス ワークフローとクライアント ワークフローの両方で使用されます。 ツールボックスの [共通 ] セクションでこのアクティビティを使用できるようにするためのソリューションをビルド します

ワークフロー サービスを実装する

  1. WorkflowServiceと呼ばれる新しい WCF ワークフロー サービスをCommon プロジェクトに追加します。 これを行うには、Common プロジェクトを右クリックし、[追加]、[新しい項目]、[インストールされているテンプレート] の [ワークフロー] の順に選択し、[WCF ワークフロー サービス] を選択します。

    ワークフロー サービスの追加

  2. 既定の ReceiveRequestSendResponse アクティビティを削除します。

  3. WriteLine アクティビティをSequential Service アクティビティにドラッグ アンド ドロップします。 次の例に示すように、text プロパティを "Workflow Service starting ..." に設定します。

    ![順次サービス アクティビティへの WriteLine アクティビティの追加 (./media/flowing-transactions-into-and-out-of-workflow-services/add-writeline-sequential-service.jpg)

  4. WriteLine アクティビティの後にTransactedReceiveScopeをドラッグ アンド ドロップします。 TransactedReceiveScopeアクティビティは、ツールボックス[メッセージング] セクションにあります。 TransactedReceiveScope アクティビティは、要求本文の 2 つのセクションで構成されます。 [要求] セクションには、Receiveアクティビティが含まれています。 [本文] セクションには、メッセージの受信後にトランザクション内で実行するアクティビティが含まれます。

    TransactedReceiveScope アクティビティの追加

  5. TransactedReceiveScopeアクティビティを選択し、[変数] ボタンをクリックします。 次の変数を追加します。

    TransactedReceiveScope への変数の追加

    既定で存在するデータ変数を削除できます。 既存のハンドル変数を使用することもできます。

  6. TransactedReceiveScope アクティビティの [要求] セクション内で、Receive アクティビティをドラッグ アンド ドロップします。 次のようにプロパティを設定します。

    プロパティ 価値
    CanCreateInstance True (チェック ボックスをオン)
    オペレーションネーム StartSample
    ServiceContractName ITransactionSample

    ワークフローは次のようになります。

    Receive アクティビティの追加

  7. Receive アクティビティの [定義...] リンクをクリックし、次の設定を行います。

    受信アクティビティのメッセージ設定の設定

  8. TransactedReceiveScopeの [本文] セクションにSequenceアクティビティをドラッグ アンド ドロップします。 Sequence アクティビティ内で、2 つのWriteLine アクティビティをドラッグ アンド ドロップし、次の表に示すようにTextプロパティを設定します。

    活動 価値
    1st WriteLine "サービス: 受信完了"
    2 番目の WriteLine "Service: Received = " + requestMessage

    ワークフローは次のようになります。

    WriteLine アクティビティを追加した後のシーケンス

  9. TransactedReceiveScope アクティビティの Body の 2 番目のWriteLine アクティビティの後に、PrintTransactionInfo アクティビティをドラッグ アンド ドロップします。

    PrintTransactionInfo を追加した後のシーケンス

  10. PrintTransactionInfo アクティビティの後にAssign アクティビティをドラッグ アンド ドロップし、次の表に従ってプロパティを設定します。

    プロパティ 価値
    移行先 replyMessage
    価値 "サービス: 応答の送信"
  11. Assign アクティビティの後にWriteLine アクティビティをドラッグ アンド ドロップし、そのText プロパティを "Service: Begin reply" に設定します。

    ワークフローは次のようになります。

    Assign と WriteLine を追加した後

  12. Receive アクティビティを右クリックし、[SendReply の作成] を選択し、最後のWriteLine アクティビティの後に貼り付けます。 SendReplyToReceive アクティビティの [定義...] リンクをクリックし、次の設定を行います。

    応答メッセージの設定

  13. SendReplyToReceive アクティビティの後にWriteLine アクティビティをドラッグ アンド ドロップし、Text プロパティを "Service: Reply sent" に設定します。

  14. ワークフローの下部にある WriteLine アクティビティをドラッグ アンド ドロップし、その Text プロパティを "サービス: ワークフローの終了、Enter キーを押して終了" に設定します。

    完成したサービス ワークフローは次のようになります。

    サービス ワークフローの完了

ワークフロー クライアントを実装する

  1. WorkflowClientと呼ばれる新しい WCF ワークフロー アプリケーションをCommon プロジェクトに追加します。 これを行うには、Common プロジェクトを右クリックし、[追加]、[新しい項目]、[インストールされているテンプレート] の下の [ワークフロー] の順に選択し、[アクティビティ] を選択します。

    アクティビティ プロジェクトを追加する

  2. Sequence アクティビティをデザイン サーフェイスにドラッグ アンド ドロップします。

  3. Sequence アクティビティ内で、WriteLine アクティビティをドラッグ アンド ドロップし、そのTextプロパティを"Client: Workflow starting"に設定します。 ワークフローは次のようになります。

    WriteLine アクティビティを追加する

  4. WriteLine アクティビティの後にTransactionScope アクティビティをドラッグ アンド ドロップします。 TransactionScopeアクティビティを選択し、[変数] ボタンをクリックして、次の変数を追加します。

    TransactionScope に変数を追加する

  5. TransactionScope アクティビティの本文にSequence アクティビティをドラッグ アンド ドロップします。

  6. 内の PrintTransactionInfo アクティビティをドラッグ アンド ドロップします。 Sequence

  7. PrintTransactionInfo アクティビティの後にWriteLine アクティビティをドラッグ アンド ドロップし、そのText プロパティを "Client: Beginning Send" に設定します。 ワークフローは次のようになります。

    クライアントの追加: 送信アクティビティの開始

  8. Assign アクティビティの後にSend アクティビティをドラッグ アンド ドロップし、次のプロパティを設定します。

    プロパティ 価値
    EndpointConfigurationName workflowServiceEndpoint
    オペレーションネーム StartSample
    ServiceContractName ITransactionSample

    ワークフローは次のようになります。

    送信アクティビティのプロパティの設定

  9. [ 定義... ] リンクをクリックし、次の設定を行います。

    アクティビティ メッセージの設定を送信する

  10. Send アクティビティを右クリックし、[ReceiveReply の作成] を選択します。 ReceiveReply アクティビティは、Send アクティビティの後に自動的に配置されます。

  11. [定義]をクリックします。..ReceiveReplyForSend アクティビティのリンクをクリックし、次の設定を行います。

    ReceiveForSend メッセージの設定

  12. SendアクティビティとReceiveReplyアクティビティの間でWriteLineアクティビティをドラッグ アンド ドロップし、そのTextプロパティを "Client: Send complete" に設定します。

  13. ReceiveReply アクティビティの後にWriteLine アクティビティをドラッグ アンド ドロップし、そのTextプロパティを "クライアント側: 受信した応答 = " + replyMessage に設定します

  14. WriteLine アクティビティの後にPrintTransactionInfo アクティビティをドラッグ アンド ドロップします。

  15. ワークフローの最後に WriteLine アクティビティをドラッグ アンド ドロップし、その Text プロパティを "クライアント ワークフローの終了" に設定します。完成したクライアント ワークフローは、次の図のようになります。

    完成したクライアント ワークフロー

  16. ソリューションをビルドします。

サービス アプリケーションを作成する

  1. Serviceという名前の新しいコンソール アプリケーション プロジェクトをソリューションに追加します。 次のアセンブリへの参照を追加します。

    1. System.Activities.dll

    2. System.ServiceModel.dll

    3. System.ServiceModel.Activities.dll

  2. 生成されたProgram.cs ファイルと次のコードを開きます。

          static void Main()  
          {  
              Console.WriteLine("Building the server.");  
              using (WorkflowServiceHost host = new WorkflowServiceHost(new DeclarativeServiceWorkflow(), new Uri("net.tcp://localhost:8000/TransactedReceiveService/Declarative")))  
              {
                  //Start the server  
                  host.Open();  
                  Console.WriteLine("Service started.");  
    
                  Console.WriteLine();  
                  Console.ReadLine();  
                  //Shutdown  
                  host.Close();  
              };
          }  
    
  3. 次の app.config ファイルをプロジェクトに追加します。

    <?xml version="1.0" encoding="utf-8" ?>  
    <!-- Copyright © Microsoft Corporation.  All rights reserved. -->  
    <configuration>  
        <system.serviceModel>  
            <bindings>  
                <netTcpBinding>  
                    <binding transactionFlow="true" />  
                </netTcpBinding>  
            </bindings>  
        </system.serviceModel>  
    </configuration>  
    

クライアント アプリケーションを作成する

  1. Clientという名前の新しいコンソール アプリケーション プロジェクトをソリューションに追加します。 System.Activities.dllへの参照を追加します。

  2. program.cs ファイルを開き、次のコードを追加します。

    class Program  
    {  
    
        private static AutoResetEvent syncEvent = new AutoResetEvent(false);  
    
        static void Main(string[] args)  
        {  
            //Build client  
            Console.WriteLine("Building the client.");  
            WorkflowApplication client = new WorkflowApplication(new DeclarativeClientWorkflow());  
            client.Completed = Program.Completed;  
            client.Aborted = Program.Aborted;  
            client.OnUnhandledException = Program.OnUnhandledException;  
            //Wait for service to start  
            Console.WriteLine("Press ENTER once service is started.");  
            Console.ReadLine();  
    
            //Start the client
            Console.WriteLine("Starting the client.");  
            client.Run();  
            syncEvent.WaitOne();  
    
            //Sample complete  
            Console.WriteLine();  
            Console.WriteLine("Client complete. Press ENTER to exit.");  
            Console.ReadLine();  
        }  
    
        private static void Completed(WorkflowApplicationCompletedEventArgs e)  
        {  
            Program.syncEvent.Set();  
        }  
    
        private static void Aborted(WorkflowApplicationAbortedEventArgs e)  
        {  
            Console.WriteLine("Client Aborted: {0}", e.Reason);  
            Program.syncEvent.Set();  
        }  
    
        private static UnhandledExceptionAction OnUnhandledException(WorkflowApplicationUnhandledExceptionEventArgs e)  
        {  
            Console.WriteLine("Client had an unhandled exception: {0}", e.UnhandledException);  
            return UnhandledExceptionAction.Cancel;  
        }  
    }  
    

こちらも参照ください