Transaktionsfluss in Workflowdienste und aus WorkflowdienstenFlowing Transactions into and out of Workflow Services

Workflowdienste und Clients können an Transaktionen teilnehmen.Workflow services and clients can participate in transactions. Damit ein Dienstvorgang Teil einer Ambient-Transaktion wird, fügen Sie eine Receive-Aktivität in eine TransactedReceiveScope-Aktivität ein.For a service operation to become part of an ambient transaction, place a Receive activity within a TransactedReceiveScope activity. Alle Aufrufe, die von einer Send-Aktivität oder einer SendReply-Aktivität in TransactedReceiveScope durchgeführt werden, werden auch in der Ambient-Transaktion durchgeführt.Any calls made by a Send or a SendReply activity within the TransactedReceiveScope will also be made within the ambient transaction. Eine Workflowclientanwendung kann mit der TransactionScope-Aktivität eine Ambient-Transaktion erstellen und Dienstvorgänge mithilfe der Ambient-Transaktion aufrufen.A workflow client application can create an ambient transaction by using the TransactionScope activity and call service operations using the ambient transaction. In diesem Thema wird die Erstellung eines Workflowdiensts und Workflowclients, die an Transaktionen teilnehmen, erläutert.This topic walks you through creating a workflow service and workflow client that participate in transactions.

Warnung

Wenn eine Workflowdienstinstanz innerhalb einer Transaktion geladen wird und der Workflow eine Persist-Aktivität enthält, bleibt die Workflowinstanz bis zum Timeout der Transaktion hängen.If a workflow service instance is loaded within a transaction and the workflow contains a Persist activity, the workflow instance will hang until the transaction times out.

Wichtig

Es wird empfohlen, bei Verwendung von TransactedReceiveScope alle empfangenen Nachrichten im Workflow in TransactedReceiveScope-Aktivitäten zu platzieren.Whenever you use a TransactedReceiveScope it is recommended to place all Receives in the workflow within TransactedReceiveScope activities.

Wichtig

Wenn Sie TransactedReceiveScope verwenden und Nachrichten in der falschen Reihenfolge eintreffen, wird beim Versuch, die erste der Nachrichten außerhalb der normalen Reihenfolge zu übermitteln, der Workflow abgebrochen.When using TransactedReceiveScope and messages arrive in the incorrect order, the workflow will be aborted when trying to deliver the first out of order message. Sie müssen sicherstellen, dass der Workflow im Leerlauf stets einen konsistenten Haltepunkt aufweist.You must make sure your workflow is always at a consistent stopping point when the workflow idles. Falls der Workflow abgebrochen wird, können Sie ihn auf diese Weise anhand eines früheren Persistenzpunkts erneut starten.This will allow you to restart the workflow from a previous persistence point should the workflow be aborted.

Erstellen einer freigegebenen BibliothekCreate a shared library

  1. Erstellen Sie eine neue leere Visual Studio-Projektmappe.Create a new empty Visual Studio Solution.

  2. Fügen Sie ein neues Klassenbibliotheksprojekt mit dem Namen Common hinzu.Add a new class library project called Common. Fügen Sie Verweise auf die folgenden Assemblys hinzu:Add references to the following assemblies:

    • System.Activities.dllSystem.Activities.dll

    • System.ServiceModel.dllSystem.ServiceModel.dll

    • System.ServiceModel.Activities.dllSystem.ServiceModel.Activities.dll

    • System.Transactions.dllSystem.Transactions.dll

  3. Fügen Sie dem PrintTransactionInfo-Projekt eine neue Klasse mit dem Namen Common hinzu.Add a new class called PrintTransactionInfo to the Common project. Diese Klasse wird von NativeActivity abgeleitet und überlädt die Execute-Methode.This class is derived from NativeActivity and overloads the Execute method.

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

    Diese native Aktivität, in der Informationen zur Ambient-Transaktion angezeigt werden, wird in den in diesem Thema verwendeten Dienst- und Clientworkflows eingesetzt.This is a native activity that displays information about the ambient transaction and is used in both the service and client workflows used in this topic. Erstellen der Projektmappe, um diese Aktivität in verfügbar zu machen die allgemeine Teil der Toolbox.Build the solution to make this activity available in the Common section of the Toolbox.

Implementieren des WorkflowdienstsImplement the workflow service

  1. Hinzufügen einer neuen WCF-Workflowdienst aufgerufen WorkflowService auf die Common Projekt.Add a new WCF Workflow Service, called WorkflowService to the Common project. Rechts klicken Sie hierzu die Common -Projekt, wählen hinzufügen, neues Element... Option Workflow unter installierte Vorlagen , und wählen Sie WCF-Workflowdienst.To do this right click the Common project, select Add, New Item ..., Select Workflow under Installed Templates and select WCF Workflow Service.

    Hinzufügen eines WorkflowdienstsAdding a Workflow Service

  2. Löschen Sie die ReceiveRequest-Standardaktivität und SendResponse-Standardaktivität.Delete the default ReceiveRequest and SendResponse activities.

  3. Ziehen Sie eine WriteLine-Aktivität in die Sequential Service-Aktivität.Drag and drop a WriteLine activity into the Sequential Service activity. Legen Sie die Texteigenschaft auf "Workflow Service starting ..." fest, wie im folgenden Beispiel gezeigt.Set the text property to "Workflow Service starting ..." as shown in the following example.

    Hinzufügen einer WriteLine-AktivitätAdding a WriteLine activity

  4. Verschieben Sie eine TransactedReceiveScope-Aktivität per Drag & Drop an die Stelle nach der WriteLine-Aktivität.Drag and drop a TransactedReceiveScope after the WriteLine activity. Die TransactedReceiveScope -Aktivität befindet sich der Messaging Teil der Toolbox.The TransactedReceiveScope activity can be found in the Messaging section of the Toolbox. Die TransactedReceiveScope Aktivität besteht aus zwei Abschnitten anfordern und Text.The TransactedReceiveScope activity is composed of two sections Request and Body. Die anfordern Abschnitt enthält die Receive Aktivität.The Request section contains the Receive activity. Die Text Abschnitt enthält die Aktivitäten, die innerhalb einer Transaktion ausgeführt wird, nachdem eine Nachricht empfangen wurde.The Body section contains the activities to execute within a transaction after a message has been received.

    Hinzufügen einer TransactedReceiveScope-AktivitätAdding a TransactedReceiveScope activity

  5. Wählen Sie die TransactedReceiveScope Aktivität, und klicken Sie auf die Variablen Schaltfläche.Select the TransactedReceiveScope activity and click the Variables button. Fügen Sie die folgenden Variablen hinzu:Add the following variables.

    Hinzufügen von Variablen zu TransactedReceiveScopeAdding Variables to the TransactedReceiveScope

    Hinweis

    Sie können die standardmäßig vorhandene Datenvariable löschen.You can delete the data variable that is there by default. Sie können auch die vorhandene Handlevariable verwenden.You can also use the existing handle variable.

  6. Drag & drop eine Receive Aktivität innerhalb der anfordern Teil der TransactedReceiveScope Aktivität.Drag and drop a Receive activity within the Request section of the TransactedReceiveScope activity. Legen Sie die folgenden Eigenschaften fest:Set the following properties:

    EigenschaftProperty WertValue
    CanCreateInstanceCanCreateInstance Wahr (aktivieren Sie das Kontrollkästchen)True (check the checkbox)
    OperationNameOperationName StartSampleStartSample
    ServiceContractNameServiceContractName ITransactionSampleITransactionSample

    Der Workflow müsste wie folgt aussehen:The workflow should look like this:

    Hinzufügen einer Receive-AktivitätAdding a Receive activity

  7. Klicken Sie auf die definieren... wiederherstellungsverknüpfung in der Receive Aktivität, und legen Sie die folgenden Einstellungen:Click the Define... link in the Receive activity and make the following settings:

    Festlegen von meldungseinstellungen für die Aktivität MeldungseinstellungenSetting message settings for the Recieve activity

  8. Ziehen Sie eine Sequence-Aktivität per Drag & Drop in den Textabschnitt vom TransactedReceiveScope.Drag and drop a Sequence activity into the Body section of the TransactedReceiveScope. Verschieben Sie innerhalb der Sequence-Aktivität zwei WriteLine-Aktivitäten per Drag & Drop, und legen Sie die Text-Eigenschaften wie in der folgenden Tabelle gezeigt fest.Within the Sequence activity drag and drop two WriteLine activities and set the Text properties as shown in the following table.

    AktivitätActivity WertValue
    1. WriteLine1st WriteLine "Service: abgeschlossene empfangen""Service: Receive Completed"
    2. WriteLine2nd WriteLine "Service: Received = " + requestMessage"Service: Received = " + requestMessage

    Der Workflow müsste jetzt wie folgt aussehen:The workflow should now look like this:

    Hinzufügen von WriteLine-AktivitätenAdding WriteLine activities

  9. Drag & drop die PrintTransactionInfo Aktivität nach der zweiten WriteLine Aktivität in der Text in die TransactedReceiveScope Aktivität.Drag and drop the PrintTransactionInfo activity after the second WriteLine activity in the Body in the TransactedReceiveScope activity.

    Nach dem Hinzufügen von PrintTransactionInfoAfter adding PrintTransactionInfo

  10. Ziehen Sie eine Assign-Aktivität per Drag & Drop an die Stelle nach der PrintTransactionInfo-Aktivität, und legen Sie die Eigenschaften entsprechend der folgenden Tabelle fest.Drag and drop an Assign activity after the PrintTransactionInfo activity and set its properties according to the following table.

    EigenschaftProperty WertValue
    BeschreibungTo replyMessagereplyMessage
    WertValue "Service: Sending reply.""Service: Sending reply."
  11. Ziehen Sie eine WriteLine-Aktivität per Drag & Drop an die Stelle nach der Assign-Aktivität, und legen Sie die Text-Eigenschaft auf "Service: Begin reply" fest.Drag and drop a WriteLine activity after the Assign activity and set its Text property to "Service: Begin reply."

    Der Workflow müsste jetzt wie folgt aussehen:The workflow should now look like this:

    Nach dem Hinzufügen von Assign und WriteLineAfter adding Assign and WriteLine

  12. Klicken Sie mit der rechten Maustaste auf die Receive Aktivität, und wählen SendReply erstellen und fügen Sie ihn nach dem letzten WriteLine Aktivität.Right click the Receive activity and select Create SendReply and paste it after the last WriteLine activity. Klicken Sie auf die definieren... wiederherstellungsverknüpfung in der SendReplyToReceive Aktivität, und legen Sie die folgenden Einstellungen.Click the Define... link in the SendReplyToReceive activity and make the following settings.

    Beantworten Sie die nachrichteneinstellungenReply message settings

  13. Drag & drop eine WriteLine Aktivität nach dem der SendReplyToReceive Aktivität, und legen sie hat Text Eigenschaft, um "Service: Reply sent."Drag and drop a WriteLine activity after the SendReplyToReceive activity and set it’s Text property to "Service: Reply sent."

  14. Verschieben Sie eine WriteLine-Aktivität per Drag & Drop an das Ende des Workflows, und legen Sie die Eigenschaft Text auf "Service: Workflow ends, press ENTER to exit" fest.Drag and drop a WriteLine activity at the bottom of the workflow and set its Text property to "Service: Workflow ends, press ENTER to exit."

    Der abgeschlossene Dienstworkflow müsste wie folgt aussehen:The completed service workflow should look like this:

    Vollständiger ServiceworkflowComplete Service Workflow

Implementieren des WorkflowclientsImplement the workflow client

  1. Fügen Sie eine neue WCF-Workflowanwendung mit dem Namen WorkflowClient zum Common-Projekt hinzu.Add a new WCF Workflow application, called WorkflowClient to the Common project. Rechts klicken Sie hierzu die Common -Projekt, wählen hinzufügen, neues Element... Option Workflow unter installierte Vorlagen , und wählen Sie Aktivität.To do this right click the Common project, select Add, New Item ..., Select Workflow under Installed Templates and select Activity.

    Hinzufügen eines AktivitätsprojektsAdd an Activity project

  2. Ziehen Sie eine Sequence-Aktivität per Drag & Drop auf die Entwurfsoberfläche.Drag and drop a Sequence activity onto the design surface.

  3. Verschieben Sie in der Sequence-Aktivität eine WriteLine-Aktivität per Drag & Drop, und legen Sie die Text-Eigenschaft auf "Client: Workflow starting" fest.Within the Sequence activity drag and drop a WriteLine activity and set its Text property to "Client: Workflow starting". Der Workflow müsste jetzt wie folgt aussehen:The workflow should now look like this:

    Hinzufügen eine WriteLine-AktivitätAdd a WriteLine activity

  4. Verschieben Sie eine TransactionScope-Aktivität per Drag & Drop an die Stelle nach der WriteLine-Aktivität.Drag and drop a TransactionScope activity after the WriteLine activity. Wählen Sie die TransactionScope-Aktivität aus, klicken Sie auf die Schaltfläche Variablen, und fügen Sie die folgenden Variablen hinzu.Select the TransactionScope activity, click the Variables button and add the following variables.

    Variablen zu TransactionScope hinzufügenAdd variables to the TransactionScope

  5. Ziehen Sie eine Sequence-Aktivität per Drag & Drop in den Text der TransactionScope-Aktivität.Drag and drop a Sequence activity into the body of the TransactionScope activity.

  6. Verschieben Sie eine PrintTransactionInfo-Aktivität per Drag & Drop innerhalb der Sequence-Aktivität.Drag and drop a PrintTransactionInfo activity within the Sequence

  7. Drag & drop eine WriteLine Aktivität nach dem die PrintTransactionInfo Aktivität, und legen dessen Text Eigenschaft auf "Client: Beginning Send".Drag and drop a WriteLine activity after the PrintTransactionInfo activity and set its Text property to "Client: Beginning Send". Der Workflow müsste jetzt wie folgt aussehen:The workflow should now look like this:

    Hinzufügen von AktivitätenAdding activities

  8. Ziehen Sie eine Send-Aktivität per Drag & Drop an die Stelle nach der Assign-Aktivität, und legen Sie die folgenden Eigenschaften fest:Drag and drop a Send activity after the Assign activity and set the following properties:

    EigenschaftProperty WertValue
    EndpointConfigurationNameEndpointConfigurationName workflowServiceEndpointworkflowServiceEndpoint
    OperationNameOperationName StartSampleStartSample
    ServiceContractNameServiceContractName ITransactionSampleITransactionSample

    Der Workflow müsste jetzt wie folgt aussehen:The workflow should now look like this:

    Festlegen der Send-AktivitätseigenschaftenSetting the Send activity properties

  9. Klicken Sie auf die definieren... verknüpfen, und legen Sie die folgenden Einstellungen:Click the Define... link and make the following settings:

    Send-aktivitätsmeldungseinstellungenSend activity message settings

  10. Klicken Sie mit der rechten Maustaste auf die Send Aktivität, und wählen ReceiveReply erstellen.Right click the Send activity and select Create ReceiveReply. Die ReceiveReply-Aktivität wird automatisch nach der Send-Aktivität platziert.The ReceiveReply activity will be automatically placed after the Send activity.

  11. Klicken Sie in der ReceiveReplyForSend-Aktivität auf den Link Definieren..., und legen Sie die folgenden Einstellungen fest:Click the Define... link on the ReceiveReplyForSend activity and make the following settings:

    Festlegen der ReceiveForSend-meldungseinstellungenSetting the ReceiveForSend message settings

  12. Verschieben Sie eine WriteLine-Aktivität per Drag & Drop zwischen der Send-Aktivität und der ReceiveReply-Aktivität, und legen Sie die Text-Eigenschaft auf "Client: Send complete" fest.Drag and drop a WriteLine activity between the Send and ReceiveReply activities and set its Text property to "Client: Send complete."

  13. Ziehen Sie eine WriteLine-Aktivität per Drag & Drop an die Stelle nach der ReceiveReply-Aktivität, und legen Sie die Text-Eigenschaft auf "Client side: Reply received = " + replyMessage fest.Drag and drop a WriteLine activity after the ReceiveReply activity and set its Text property to "Client side: Reply received = " + replyMessage

  14. Verschieben Sie eine PrintTransactionInfo-Aktivität per Drag & Drop an die Stelle nach der WriteLine-Aktivität.Drag and drop a PrintTransactionInfo activity after the WriteLine activity.

  15. Verschieben Sie eine WriteLine-Aktivität per Drag & Drop an das Ende des Workflows, und legen Sie die Text-Eigenschaft auf "Client workflow ends" fest.Drag and drop a WriteLine activity at the end of the workflow and set its Text property to "Client workflow ends." Der abgeschlossene Clientworkflow sollte wie das folgende Diagramm aussehen.The completed client workflow should look like the following diagram.

    Der abgeschlossene clientworkflowThe completed client workfliow

  16. Erstellen Sie die Projektmappe.Build the solution.

Erstellen der DienstanwendungCreate the Service application

  1. Fügen Sie der Projektmappe ein neues Konsolenanwendungsprojekt mit dem Namen Service hinzu.Add a new Console Application project called Service to the solution. Fügen Sie Verweise auf die folgenden Assemblys hinzu:Add references to the following assemblies:

    1. System.Activities.dllSystem.Activities.dll

    2. System.ServiceModel.dllSystem.ServiceModel.dll

    3. System.ServiceModel.Activities.dllSystem.ServiceModel.Activities.dll

  2. Öffnen Sie die generierte Datei Program.cs und den folgenden Code:Open the generated Program.cs file and the following code:

    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. Fügen Sie dem Projekt die folgende app.config-Datei hinzu.Add the following app.config file to the project.

    <?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>  
    

Erstellen der ClientanwendungCreate the client application

  1. Fügen Sie der Projektmappe ein neues Konsolenanwendungsprojekt mit dem Namen Client hinzu.Add a new Console Application project called Client to the solution. Fügen Sie einen Verweis auf System.Activities.dll hinzu.Add a reference to System.Activities.dll.

  2. Öffnen Sie die Datei program.cs, und fügen Sie den folgenden Code hinzu.Open the program.cs file and add the following code.

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

Siehe auchSee Also

WorkflowdiensteWorkflow Services
Übersicht über Windows Communication Foundation-TransaktionenWindows Communication Foundation Transactions Overview
Verwendung von TransactedReceiveScopeUse of TransactedReceiveScope