Freigeben über


Beispiel für Unterhaltungen

Dieses Beispiel veranschaulicht, wie ein Workflowdienst parallele Konversationen mit mehreren Clients über den gleichen Vertrag führen kann. Das Beispiel zeigt, wie Nachrichten korreliert werden, die für den gleichen Vertrag und den gleichen Vorgang gesendet werden, aber unterschiedlich gehandhabt werden müssen, da sie von verschiedenen Clients gesendet werden. In diesem Beispiel wird die von Workflowdiensten bereitgestellte Konversationskontextfunktionalität verwendet, um parallele Konversationen zu erreichen.

Tipp

Zum Erstellen und Ausführen dieses Beispiels muss .NET Framework, Version 3.5 installiert sein. Zum Öffnen des Projekts und der Projektmappendateien ist Visual Studio 2008 erforderlich.

Weitere Informationen zum Einrichten dieses Beispiels finden Sie unter One-time Setup Procedure for Windows Communication Foundation Samples.

In diesem Beispiel wird darüber hinaus asynchrone Duplexkommunikation verwendet, sodass der Workflowdienst und der Client asynchron kommunizieren können. Bei der Duplexkommunikation müssen die zwei Anwendungen vor Kommunikationsbeginn einen Kontext austauschen. Der Dienst, der die Konversation initiiert, empfängt den Kontext in der Antwort auf seine Nachricht. Workflowdienste verfügen über diese Funktionalität. Damit die Kommunikation vom empfangenden Dienst zum initiierenden Dienst unterstützt wird, muss der initiierende Dienst die Kontextinformationen in der ersten Nachricht senden. Die Architektur des Beispiels ist in der folgenden Abbildung dargestellt.

Architektur des Konversationsbeispiels

Beispiel für Unterhaltungen

Dieses Beispiel implementiert das folgende Szenario.

Ein Kunde sendet eine Bestellanforderung. Als Reaktion hierauf möchte der Lieferant Angebote von drei unterschiedlichen Logistikanbietern für den Versand der Bestellung einholen. Der Lieferant schickt allen drei Anbietern eine Nachricht. Jeder Anbieter sendet ein Angebot zurück, indem er auf dem gleichen Vertrag den gleichen Vorgang aufruft. Da der Lieferantenworkflow den Konversationskontext verwendet, kann die Funktionalität die Angebote für eine Weiterverarbeitung mit der richtigen Empfangsaktivität korrelieren. Der Lieferant empfängt alle Angebote, wählt das Niedrigste aus und schickt es dem Kunden.

Fünf Entitäten kommunizieren in diesem Beispiel:

  • Kundendienst
    Der Kundendienst sendet die Bestellinformationen zusammen mit einem Kontext, den der Lieferantendienst später nutzt, um wieder mit dem Kundendienst zu kommunizieren, an den Lieferanten. Dieser grundlegende Workflow enthält eine anfängliche Send-Aktivität, die die Nachricht mit der Bestellanforderung und dem Kontext als Nutzlast sendet. Eine Receive-Aktivität wartet auf eine Antwort vom Lieferantendienst.
    Der vom Kundendienst gesendete Kontext ist mit der Empfangsaktivität verknüpft. Der "Before send"-Handler der Sendeaktivität enthält Code, der den Kontext von derReceive-Aktivität abruft. Die Receive-Aktivität umfasst die folgende GetContext-Methode, die aufgerufen wird, um den Kontext zu erhalten.

    private void PrepareOrder(object sender, SendActivityEventArgs e)
    {
        this.order.Amount = 1000;
        this.order.OrderId = 1234;
        this.contextToSend = this.ReceiveOrderDetails.Context;
    }
    
  • Lieferantendienst
    Der Lieferantendienst kommuniziert mit drei Logistikanbietern. Um dies zu erreichen, nutzt er eine Kombination aus einem eindeutigen Kontexttoken für jede Konversation und asynchroner Duplexkommunikation. Er sendet den Kontext im Nachrichtentext der Kommunikation zwischen dem Kunden- und Lieferantendienst.
    Vor der Kommunikation mit den Logistikanbietern empfängt der Lieferantendienst zuerst die Nachricht vom Kundendienst. In dieser Nachricht empfängt der Lieferantendienst darüber hinaus den Kontext, den er verwendet, um mit dem Kundendienst zu kommunizieren. Der Workflow des Lieferantendiensts wendet diesen Kontext auf die Send-Aktivität an, die verwendet wird, um eine Nachricht an den Clientdienst zu senden. Der Code, der diese Funktionalität implementiert, befindet sich im Codehandler der Codeaktivität innerhalb der ersten Receive-Aktivität (wie im folgenden Code gezeigt).

    private void AcceptOrder(object sender, EventArgs e)
    {
        Console.WriteLine("Order Received...");
        this.supplierAck = "Order Received on " + DateTime.Now;
        this.SendOrderDetails.Context = this.customerContext;
    }
    

    Sobald der Lieferantendienst eine Nachricht vom Kunden empfängt, initiiert der Lieferant drei parallele Konversationen mit drei Logistikanbietern. Jede Konversationsverzweigung verfügt, wie in der vorherigen Illustration gezeigt, über eine Send-Aktivität und eine Receive-Aktivität. Die Send-Aktivitäten in jeder Verzweigung senden die Nachricht an einen Logistiklieferanten. Die entsprechende Receive-Aktivität in dieser Verzweigung muss die Nachricht vom Lieferanten abrufen. Um dies zu erreichen, muss die Send-Aktivität in der Nachrichtennutzlast einen eindeutigen Kontext in der Nutzlast senden. Der Logistikanbieter verwendet dann diesen Kontext im Nachrichtenheader, wenn er die Nachricht mit dem Angebot zurücksendet.
    Standardmäßig verfügt jede Receive-Aktivität über einen Stammkontext. Um die Receive-Aktivität eindeutig zu gestalten, definiert die Receive-Aktivität einen Kontext, der auf eine andere übergeordnete Aktivität als die Stammaktivität festgelegt ist. Im folgenden Beispiel verfügt die Kontexttokeneigenschaft jeder Receive-Aktivität in der parallelen Konversation über einen eindeutigen Namen und ist auf die parallele Aktivität festgelegt, in der sie enthalten ist. Wenn die Sendeaktivität innerhalb einer jeden parallelen Verzweigung einen Kontext von der Receive-Aktivität erhält, ist dieser Kontext für diese Receive-Aktivität eindeutig. Dieser eindeutige Kontext wird darüber hinaus verwendet, um einen Warteschlangennamen für die Warteschlange zu erstellen, die von der Receive-Aktivität überwacht wird. Wenn der Logistikanbieter sein Angebot mit dem Kontext im Header zurücksendet, nutzt die Workflow-Dienstverteilungsebene diesen, um den entsprechenden Warteschlangennamen zu erstellen und die Nachricht in die Warteschlange zu verschieben, die dann von der Receive-Aktivität eingesehen wird.
    private void PrepareShipper2Request(object sender, SendActivityEventArgs e)
    {
    Console.ForegroundColor = ConsoleColor.Green;
    Console.WriteLine("RequestShippingQuote from Shipper2");
    Console.ResetColor();
    this.contextShipper2 = this.ReceiveQuoteFromShipper2.Context;
    }
    Die Logistikanbieterworkflows empfangen die Bestellanforderungen vom Lieferanten zusammen mit dem Kontext. Dieser Kontext wird für die Send-Aktivität übernommen, die die Nachricht zurück zum Lieferanten sendet (siehe folgender Code).

    private void AcceptQuoteRequest(object sender, EventArgs e)
    {
        Console.ForegroundColor = ConsoleColor.White;
        Console.WriteLine("Received ShippingQuote Request");
        this.supplierAck = "Working on quote...";
        Console.ResetColor();
        this.SendShippingQuote.Context(this.supplierContext);
    }
    

So richten Sie das Beispiel ein, erstellen es und führen es aus

  1. Standardmäßig wird in diesem Beispiel nicht Persistenz verwendet. Wenn Sie Persistenz benötigen, müssen Sie den <WorkflowRuntime>-Eintrag in der Datei "App.config" jeder Projektmappe hinzufügen. Der Eintrag sollte, wie im folgenden Beispiel veranschaulicht, unter dem Abschnitt behaviors erfolgen.

    <behaviors>
          <serviceBehaviors>
            <behavior name="ServiceBehavior"  >
              <serviceMetadata httpGetEnabled="false" />
              <serviceDebug includeExceptionDetailInFaults="true" />
              <workflowRuntime name="WorkflowServiceHostRuntime" validateOnCreate="true" enablePerformanceCounters="true">
                <services>
                  <add type="System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                       connectionString="Data Source=localhost\sqlexpress;Initial Catalog=ServiceModelSamples_ServiceWorkflowStore;Integrated Security=True;Pooling=False"
                       LoadIntervalSeconds="1" UnLoadOnIdle= "true" />
                </services>
              </workflowRuntime>
            </behavior>
          </serviceBehaviors>
        </behaviors>
    
  2. Zusätzlich zum <WorkflowRuntime>-Eintrag unter dem Abschnitt behaviors wird ein SQL Persistence Service hinzugefügt. Führen Sie das Skript CreateStores.cmd aus dem Thema One-Time Setup Procedure for the Windows Communication Foundation Samples aus. Das Skript CreateStores.cmd erstellt die Datenbank ServiceModelSamples_ServiceWorkflowStore. Standardmäßig werden diese Datenbanken in einer SQL Server 2005 Express Edition-Datenbank erstellt. Stellen Sie sicher, dass SQL Server Express auf ihrem Computer installiert ist. Wenn Sie SQL Server Express nicht installieren möchten und stattdessen SQL Server bevorzugen, müssen Sie die Verbindungszeichenfolgen in den App.config-Dateien für die Persistenzdatenbanken ändern.

  3. Sobald alle Workflowdienste ausgeführt werden, betätigen Sie die EINGABETASTE im Clientworkflow, um alle Workflows anzuzeigen, die miteinander kommunizieren. Die Bestellung wird an den Lieferanten gesendet, der wiederum Angebotsanforderungen an alle Logistikanbieter sendet. Sobald der Lieferant Angebote empfängt, sehen Sie, dass das niedrigste Angebot zum Kunden zurückgesendet wird. Sie können auch die Kontexttoken für jeden Fall überprüfen. Dies erleichtert es, die eindeutigen Kontexte zu verstehen, die an jeden Logistikanbieter gesendet werden.

Senden Sie Kommentare zu diesem Thema an Microsoft.