Delen via


Transacties naar en uit workflowservices stromen

Werkstroomservices en -clients kunnen deelnemen aan transacties. Als u een servicebewerking wilt laten deelnemen aan een omgevingstransactie, plaatst u een Receive activiteit binnen een TransactedReceiveScope activiteit. Alle aanroepen van een Send of een SendReply activiteit binnen de TransactedReceiveScope activiteit worden ook uitgevoerd binnen de omgevingstransactie. Een werkstroomclienttoepassing kan een omgevingstransactie maken met behulp van de TransactionScope activiteits- en oproepservicebewerkingen met behulp van de omgevingstransactie. In dit onderwerp wordt uitgelegd hoe u een werkstroomservice en werkstroomclient maakt die deelneemt aan transacties.

Waarschuwing

Als een werkstroomservice-exemplaar wordt geladen binnen een transactie en de werkstroom een Persist activiteit bevat, wordt het werkstroomexemplaren geblokkeerd totdat er een time-out optreedt voor de transactie.

Belangrijk

Wanneer u een TransactedReceiveScope app gebruikt, wordt aanbevolen om alle ontvangstbewerkingen in de werkstroom binnen TransactedReceiveScope activiteiten te plaatsen.

Belangrijk

Wanneer het gebruik TransactedReceiveScope en de berichten in de verkeerde volgorde binnenkomen, wordt de werkstroom afgebroken wanneer het eerste bericht buiten de order wordt bezorgd. U moet ervoor zorgen dat uw werkstroom altijd op een consistent stoppunt staat wanneer de werkstroom inactief is. Hierdoor kunt u de werkstroom opnieuw starten vanaf een eerder persistentiepunt als de werkstroom wordt afgebroken.

Een gedeelde bibliotheek maken

  1. Maak een nieuwe lege Visual Studio-oplossing.

  2. Voeg een nieuw klassebibliotheekproject toe met de naam Common. Voeg verwijzingen toe aan de volgende assembly's:

    • System.Activities.dll

    • System.ServiceModel.dll

    • System.ServiceModel.Activities.dll

    • System.Transactions.dll

  3. Voeg een nieuwe klasse toe die aan het Common project wordt aangeroepenPrintTransactionInfo. Deze klasse is afgeleid van NativeActivity en overbelast de Execute methode.

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

    Dit is een systeemeigen activiteit die informatie weergeeft over de omgevingstransactie en wordt gebruikt in zowel de service- als clientwerkstromen die in dit onderwerp worden gebruikt. Bouw de oplossing om deze activiteit beschikbaar te maken in de sectie Algemeen van de Werkset.

De werkstroomservice implementeren

  1. Voeg een nieuwe WCF-werkstroomservice toe, aangeroepen WorkflowService aan het Common project. Als u dit wilt doen, klikt u met de rechtermuisknop op het Common project, selecteert u Toevoegen, Nieuw item ..., selecteert u Werkstroom onder Geïnstalleerde sjablonen en selecteert u WCF-werkstroomservice.

    Adding a Workflow Service

  2. Verwijder de standaard ReceiveRequest - en SendResponse activiteiten.

  3. Sleep een WriteLine activiteit naar de activiteit en zet deze Sequential Service neer. Stel de teksteigenschap in op "Workflow Service starting ..." zoals wordt weergegeven in het volgende voorbeeld.

    ! [Een WriteLine-activiteit toevoegen aan de sequentiële serviceactiviteit (./media/flowing-transactions-into-and-out-of-workflow-services/add-writeline-sequential-service.jpg)

  4. Sleep een TransactedReceiveScope na de activiteit en zet deze WriteLine neer. De TransactedReceiveScope activiteit vindt u in de sectie Berichten van de Werkset. De TransactedReceiveScope activiteit bestaat uit twee secties Aanvraag en Hoofdtekst. De sectie Aanvraag bevat de Receive activiteit. De sectie Hoofdtekst bevat de activiteiten die binnen een transactie moeten worden uitgevoerd nadat een bericht is ontvangen.

    Adding a TransactedReceiveScope activity

  5. Selecteer de TransactedReceiveScope activiteit en klik op de knop Variabelen . Voeg de volgende variabelen toe.

    Adding variables to the TransactedReceiveScope

    Notitie

    U kunt de gegevensvariabele die er standaard is, verwijderen. U kunt ook de bestaande handlevariabele gebruiken.

  6. Sleep een Receive activiteit in de sectie Aanvraag van de activiteit en zet deze TransactedReceiveScope neer. Stel de volgende eigenschappen in:

    Eigenschappen Weergegeven als
    CanCreateInstance Waar (schakel het selectievakje in)
    OperationName StartSample
    ServiceContractName ITransactionSample

    De werkstroom moet er als volgt uitzien:

    Adding a Receive activity

  7. Klik op de koppeling Definiëren... in de Receive activiteit en voer de volgende instellingen uit:

    Setting message settings for the Receive activity

  8. Sleep een Sequence activiteit en zet deze neer in de sectie Hoofdtekst van de TransactedReceiveScope. Sleep twee WriteLine activiteiten binnen de Sequence activiteit en zet deze neer en stel de Text eigenschappen in zoals wordt weergegeven in de volgende tabel.

    Activiteit Weergegeven als
    1e WriteLine "Service: Ontvangen voltooid"
    2e WriteLine "Service: Received = " + requestMessage

    De werkstroom moet er nu als volgt uitzien:

    Sequence after adding WriteLine activities

  9. Sleep de activiteit en zet deze PrintTransactionInfo neer na de tweede WriteLine activiteit in de hoofdtekst van de TransactedReceiveScope activiteit.

    Sequence after adding PrintTransactionInfo

  10. Sleep een Assign activiteit na de PrintTransactionInfo activiteit en stel de eigenschappen ervan in volgens de volgende tabel.

    Eigenschappen Weergegeven als
    Tot replyMessage
    Weergegeven als "Service: Antwoord verzenden."
  11. Sleep een WriteLine activiteit na de activiteit en stel de Assign eigenschap ervan in Text op 'Service: Begin antwoord'.

    De werkstroom moet er nu als volgt uitzien:

    After adding Assign and WriteLine

  12. Klik met de rechtermuisknop op de Receive activiteit en selecteer SendReply maken en plak deze na de laatste WriteLine activiteit. Klik op de koppeling Definiëren... in de SendReplyToReceive activiteit en voer de volgende instellingen uit.

    Reply message settings

  13. Sleep een WriteLine activiteit na de SendReplyToReceive activiteit en stel deze eigenschap in Text op 'Service: Antwoord verzonden'.

  14. Sleep een WriteLine activiteit onder aan de werkstroom en stel de eigenschap in Text op 'Service: Werkstroom eindigt, druk op Enter om af te sluiten'.

    De voltooide servicewerkstroom moet er als volgt uitzien:

    Complete Service Workflow

De werkstroomclient implementeren

  1. Voeg een nieuwe WCF-werkstroomtoepassing toe, aangeroepen WorkflowClient aan het Common project. Als u dit wilt doen, klikt u met de rechtermuisknop op het Common project, selecteert u Toevoegen, Nieuw item ..., selecteert u Werkstroom onder Geïnstalleerde sjablonen en selecteert u Activiteit.

    Add an Activity project

  2. Sleep een Sequence activiteit naar het ontwerpoppervlak en zet deze neer.

  3. Sleep een WriteLine activiteit binnen de Sequence activiteit en zet deze neer en stel de eigenschap in Text op "Client: Workflow starting". De werkstroom moet er nu als volgt uitzien:

    Add a WriteLine activity

  4. Sleep een TransactionScope activiteit en zet deze neer na de WriteLine activiteit. Selecteer de TransactionScope activiteit, klik op de knop Variabelen en voeg de volgende variabelen toe.

    Add variables to the TransactionScope

  5. Sleep een Sequence activiteit naar de hoofdtekst van de activiteit en zet deze TransactionScope neer.

  6. Een activiteit slepen en neerzetten PrintTransactionInfo binnen de Sequence

  7. Sleep een WriteLine activiteit na de activiteit en stel Text de PrintTransactionInfo eigenschap ervan in op 'Client: Begin verzenden'. De werkstroom moet er nu als volgt uitzien:

    Adding Client: Beginning Send activities

  8. Sleep een Send activiteit na de Assign activiteit en stel de volgende eigenschappen in:

    Eigenschappen Weergegeven als
    EndpointConfigurationName workflowServiceEndpoint
    OperationName StartSample
    ServiceContractName ITransactionSample

    De werkstroom moet er nu als volgt uitzien:

    Setting the Send activity properties

  9. Klik op de koppeling Definiëren... en voer de volgende instellingen in:

    Send activity message settings

  10. Klik met de rechtermuisknop op de Send activiteit en selecteer ReceiveReply maken. De ReceiveReply activiteit wordt automatisch na de Send activiteit geplaatst.

  11. Klik op definiëren... link op de ReceiveReplyForSend-activiteit en maak de volgende instellingen:

    Setting the ReceiveForSend message settings

  12. Sleep een WriteLine activiteit tussen de activiteiten en ReceiveReply stel de SendText eigenschap in op 'Client: Send complete'.

  13. Sleep een WriteLine activiteit na de activiteit en stel de ReceiveReply eigenschap ervan in Text op 'Clientzijde: Beantwoorden ontvangen = ' + replyMessage

  14. Sleep een PrintTransactionInfo activiteit en zet deze neer na de WriteLine activiteit.

  15. Sleep een WriteLine activiteit aan het einde van de werkstroom en zet Text deze neer op 'Client workflow ends'. De voltooide clientwerkstroom moet eruitzien als in het volgende diagram.

    The completed client workflow

  16. Bouw de oplossing.

De servicetoepassing maken

  1. Voeg een nieuw consoletoepassingsproject toe dat aan de oplossing wordt aangeroepen Service . Voeg verwijzingen toe aan de volgende assembly's:

    1. System.Activities.dll

    2. System.ServiceModel.dll

    3. System.ServiceModel.Activities.dll

  2. Open het gegenereerde Program.cs-bestand en de volgende 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. Voeg het volgende bestand app.config toe aan het 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>  
    

De clienttoepassing maken

  1. Voeg een nieuw consoletoepassingsproject toe dat aan de oplossing wordt aangeroepen Client . Voeg een verwijzing toe naar System.Activities.dll.

  2. Open het program.cs-bestand en voeg de volgende code toe.

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

Zie ook