Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In dieser Aufgabe erstellen Sie einen grundlegenden Statuscomputer-Workflowdienst, mit dem ein Windows Communication Foundation (WCF)-Vertrag implementiert wird und die Zustandsinformationen des Diensts dauerhaft in einer SQL-Datenbank gespeichert werden. Der Dienst wird mithilfe des Erstellungsformats Vertrag zuerst erstellt.
Tipp
Dieser Workflowdienst wird in den restlichen Übungen in diesem Lernprogramm verwendet.
Tipp
Wird der Workflow-Designer von Visual Studio zum Erstellen oder Verwalten von Workflowdiensten verwendet, werden dadurch gelegentlich unechte Validierungsfehler verursacht. Falls Sie das Projekt erfolgreich erstellen können, ignorieren Sie die Auswertungsfehler.
So richten Sie den Workflowdienst ein und definieren den Vertrag:
Öffnen Sie Visual Studio 2008, klicken Sie auf Datei, wählen Sie Neu und anschließend Projekt aus.
Wählen Sie im Dialogfeld Neues Projekt unter WCF die Vorlage Statuscomputerworkflow-Dienstbibliothek aus.
Nennen Sie das Projekt WorkflowServiceTutorial, und klicken Sie auf OK.
Visual Studio 2008 generiert die folgenden Dateien für den Workflowdienst: eine Datei vom Typ App.config zum Speichern von Konfigurationseinstellungen mithilfe desselben Schemas, das für WCF-Dienste verwendet wird, einer Quelldatei, die eine Vertragsdefinition beinhaltet und der Workflowklassen-Quelldateien, die den Designercode und den Implementierungscode für den Workflow definieren.
Mit der Vorlage wird ein Statuscomputerworkflow mit zwei StateActivity-Aktivitäten erstellt. Die erste StateActivity-Aktivität (Workflow1InitialState) beinhaltet eine EventDrivenActivity-Aktivität, die selbst eine ReceiveActivity-Aktivität gefolgt von einer SetStateActivity-Aktivität beinhaltet. Bei der SetStateActivity-Aktivität ist die TargetStateName-Eigenschaft auf den Namen der anderen StateActivity-Aktivität im Statuscomputerworkflow festgelegt.
Der ReceiveActivity-Typ selbst wird von SequenceActivity abgeleitet und kann daher mehrere untergeordnete Aktivitäten beinhalten, die der Reihenfolge nach ausgeführt werden. Die Implementierung einer ReceiveActivity-Aktivität gleicht der Implementierung eines Vorgangs in einem standardmäßigen WCF-Dienst. Doch anstatt den Code im Text einer Methode zu implementieren, werden die Aktionen mithilfe von WF-Aktivitäten implementiert.
Mit den ReceiveActivity-Aktivitäten in diesem Lernprogramm werden mehrere neue in IWorkflow1.cs definierte Vorgänge implementiert (oder IWorkflow1.vb, falls Sie eine Visual Basic-Projektmappe erstellt haben). Dabei handelt es sich um Anforderungs-/Antwortvorgänge; daher empfängt der Client eine Nachricht vom Dienst.
Da Sie einen bereits vorhandenen WCF-Vertrag verwenden, wird dies als Vertrag zuerst-Format für das Erstellen eines Workflowdiensts bezeichnet. Wenn Sie einen neuen Vertrag programmgesteuert erstellen möchten finden Sie unter How to: Implement a Windows Communication Foundation Contract Operation entsprechende Informationen.
Da Sie neue Vorgänge in der Schnittstelle definieren, öffnen Sie IWorkflow1.cs (oder IWorkflow1.vb, sofern Sie eine Visual Basic-Projektmappe erstellt haben), und ersetzen Sie die vorhandene Schnittstellendefinition mit Code aus dem folgenden Beispiel:
<ServiceContract()> _ Public Interface IWorkflow1 <OperationContract()> _ Sub StartupService() <OperationContract()> _ Function Add(ByVal n1 As Integer) As Integer <OperationContract()> _ Function Subtract(ByVal n1 As Integer) As Integer <OperationContract()> _ Function Multiply(ByVal n1 As Integer) As Integer <OperationContract()> _ Function Divide(ByVal n1 As Integer) As Integer <OperationContract()> _ Sub ShutdownService() End Interface[ServiceContract] public interface IWorkflow1 { [OperationContract] void StartupService(); [OperationContract] int Add(int n1); [OperationContract] int Subtract(int n1); [OperationContract] int Multiply(int n1); [OperationContract] int Divide(int n1); [OperationContract] void ShutdownService(); }
So implementieren Sie den Dienstvertrag:
Wird der Workflow-Designer nicht angezeigt, öffnen Sie den Designer, indem Sie mit der rechten Maustaste auf Workflow1.cs klicken (oder Workflow1.vb, falls Sie eine Visual Basic-Lösung erstellt haben) und Ansicht-Designer auswählen.
Ziehen Sie eine StateActivity-Aktivität in den Statuscomputerworkflow. Benennen Sie die Aktivität in OperationsState um.
Benennen Sie stateActivity1 in FinalState um.
Tipp
Wird diese Aktivität umbenannt, wird sie nicht mehr als abgeschlossener Status des Workflows gekennzeichnet; klicken Sie daher im Workflow-Designer mit der rechten Maustaste auf FinalState, und wählen Sie Status als "Abgeschlossen" festlegen aus.
Wählen Sie in der StateActivity-Aktivität mit der Bezeichnung Workflow1InitialState eventDrivenActivity1 aus, und nehmen Sie eine Umbenennung in WaitToStartService vor.
Doppelklicken Sie auf WaitToStartService, um diesen zu erweitern. Eine ReceiveActivity-Aktivität wurde bereits als untergeordnete Aktivität von WaitToStartService festgelegt.
Wählen Sie receiveActivity1 aus, und klicken Sie im Bereich Eigenschaften unter ServiceOperationInfo auf die Ellipse zum Öffnen des Dialogfelds Vorgang auswählen.
Wählen Sie StartupService aus, und klicken Sie auf OK.
Wählen Sie im Bereich Eigenschaften unter CanCreateInstance im Dropdownmenü True aus. Dies bedeutet, dass eine Instanz des Workflows erstellt wird, wenn der StartupService-Vorgang aufgerufen wird. Der Standardwert für diese Eigenschaft ist auf False festgelegt, und falls zum Zeitpunkt des Vorgangsaufrufs noch keine Kontext-ID zwischen dem Client und dem Dienst eingerichtet war, erhält der Client die folgende Nachricht:
There is no context attached to incoming message for the service and the current operation is not marked with "CanCreateInstance = true". In order to communicate with this service check whether the incoming binding supports the context protocol and has a valid context initialized.Wählen Sie in der Workflow1InitialState-Entwurfsansicht setStateActivity1 aus.
Ändern Sie im Bereich Eigenschaften den Namen für die TargetStateName-Eigenschaft von stateActivity1 in OperationsState.
Navigieren Sie zurück zur Hauptworkflow-Designeransicht. Im Normalfall besteht nun eine Verbindung zwischen Workflow1InitialState und OperationsState.
Verschieben Sie fünf EventDrivenActivity-Aktivitäten per Drag & Drop in die StateActivity-Aktivität von OperationsState, und nennen Sie sie WaitToAdd, WaitToSubtract, WaitToMultiply, WaitToDivide und WaitToEndService.
Doppelklicken Sie auf WaitToAdd, um diese Aktivität zu erweitern.
Verschieben Sie Sie eine ReceiveActivity-Aktivität per Drag & Drop in WaitToAdd.
Klicken Sie im Bereich Eigenschaften unter ServiceOperationInfo auf die Ellipse, um das Dialogfeld Vorgang auswählen zu öffnen.
Wählen Sie Hinzufügen aus, und klicken Sie auf OK.
Verschieben Sie eine CodeActivity-Aktivität per Drag & Drop in die ReceiveActivity-Aktivität.
Klicken Sie im Bereich Eigenschaften auf die Schaltfläche Ereignisse.
Doppelklicken Sie in das Textfeld für das ExecuteCode-Ereignis, um automatisch eine Ereignishandlermethode für das ExecuteCode-Ereignis zu generieren.
Öffnen Sie Workflow1.cs (oder Workflow1.vb, falls Sie eine Visual Basic-Projektmappe erstellt haben), benennen Sie die Klasse in ServerWorkflow um, und ändern Sie die von der Vorlage erstellten Variablendeklarationen für returnValue und inputValue wie folgt:
Public class ServerWorkflow Inherits StateMachineWorkflowActivity Public returnValue As Int32 Public inputValue As Int32 Private Sub codeActivity1_ExecuteCode(ByVal sender As System.Object, ByVal e As System.EventArgs) End Sub End Classpublic sealed partial class ServerWorkflow : StateMachineWorkflowActivity { public ServerWorkflow() { InitializeComponent(); } public int returnValue = default(int);public int inputValue = default(int); private void codeActivity1_ExecuteCode(object sender, EventArgs e) { } }Navigieren Sie zum Ereignishandler für ExecuteCode.
Weisen Sie returnValue im Text des Ereignishandlers dem folgenden Wert zu:
Private Sub codeActivity1_ExecuteCode(ByVal sender As System.Object, ByVal e As System.EventArgs) returnValue += inputValue End Subprivate void codeActivity1_ExecuteCode(object sender, EventArgs e) { returnValue += inputValue; }Kehren Sie zur OperationsState-Designeransicht zurück, klicken Sie auf die Add ReceiveActivity-Aktivität, und binden Sie im Bereich Eigenschaften die n1- und (ReturnValue) -Parameter an inputValue bzw. returnValue. Markieren Sie dazu die beiden Parameter, und klicken Sie auf die Schaltfläche mit den Auslassungszeichen. Durch diese Aktion wird das Dialogfeld für die Eigenschaftenbindung geöffnet, in dem die entsprechende Membereigenschaft ausgewählt werden kann, an die ein Parameter gebunden wird.
Behalten Sie im Bereich Eigenschaften zudem die Festlegung von CanCreateInstance auf False bei, um weiterhin dieselbe Instanz, die in Schritt 8 erstellt wurde, zu verwenden. Andernfalls wird durch Festlegen von CanCreateInstance auf True bei jedem Vorgangsaufruf eine neue Workflowinstanz erstellt.
Fügen Sie die ReceiveActivity-Aktivität und die CodeActivity-Aktivität für jede der verbleibenden EventDrivenActivity-Aktivitäten hinzu (beginnend mit WaitToSubtract). Denken Sie auch daran, die Vorgangsparameter mit den globalen Variablen inputValue und returnValue zu binden.
Sind alle Schritte ausgeführt, besitzt jeder Rechenvorgang eine zugewiesene ReceiveActivity, und alle CodeActivity-Aktivitätsereignishandler sollten folgendermaßen implementiert werden:
Private Sub codeActivity1_ExecuteCode(ByVal sender As System.Object, ByVal e As System.EventArgs) returnValue += inputValue End Sub Private Sub codeActivity2_ExecuteCode(ByVal sender As System.Object, ByVal e As System.EventArgs) returnValue -= inputValue End Sub Private Sub codeActivity3_ExecuteCode(ByVal sender As System.Object, ByVal e As System.EventArgs) returnValue *= inputValue End Sub Private Sub codeActivity4_ExecuteCode(ByVal sender As System.Object, ByVal e As System.EventArgs) returnValue /= inputValue End Subprivate void codeActivity1_ExecuteCode(object sender, EventArgs e) { returnValue += inputValue; } private void codeActivity2_ExecuteCode(object sender, EventArgs e) { returnValue -= inputValue; } private void codeActivity3_ExecuteCode(object sender, EventArgs e) { returnValue *= inputValue; } private void codeActivity4_ExecuteCode(object sender, EventArgs e) { returnValue /= inputValue; }Verschieben Sie für die WaitToEndService EventDrivenActivity-Aktivität eine ReceiveActivity-Aktivität per Drag & Drop in WaitToEndService.
Klicken Sie im Bereich Eigenschaften unter ServiceOperationInfo auf die Ellipse, um das Dialogfeld Vorgang auswählen zu öffnen.
Wählen Sie ShutdownService aus, und klicken Sie auf OK.
Verschieben Sie in der OperationsState-Entwurfsansicht unter der ReceiveActivity-Aktivität SetStateActivity per Drag & Drop in WaitToEndService.
Wählen Sie die SetStateActivity-Aktivität aus, und wählen Sie im Bereich Eigenschaften unter TargetStateName in der Dropdownliste FinalState aus.
So behalten Sie den Workflowdienst bei:
Öffnen Sie die Datei App.config.
Fügen Sie wie unten dargestellt einen Verweis auf SqlWorkflowPersistenceService im Verhaltenselement hinzu.
<behavior name="WorkflowServiceTutorial.ServerWorkflowBehavior" > <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="true" /> <serviceCredentials> <windowsAuthentication allowAnonymousLogons="false" includeWindowsGroups="true" /> </serviceCredentials> <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=NetFx35Samples_ServiceWorkflowStore;Integrated Security=True;Pooling=False" LoadIntervalSeconds="1" UnLoadOnIdle= "true" /> </services> </workflowRuntime> </behavior>Der in diesem Lernprogramm verwendete SqlWorkflowPersistenceService ist ein Persistenzdienst, der in reinen Workflowszenarios verwendet werden kann. Dies bedeutet, dass die Workflowzustandsinformationen immer in einer SQL-Datenbank gespeichert werden, wenn sich die Workflowinstanz im Leerlauf befindet. Dieses Szenario wird standardmäßig in .NET Framework, Version 3.5 unterstützt, doch es sind Ableitungen von WorkflowPersistenceService möglich, um Daten dauerhaft in anderen Datenbankspeichern zu speichern.
Da der Workflowdienst die Persistenzfunktion von Windows Workflow Foundation verwenden kann, können Workflowzustandsinformationen während der Ausführung einer Vorgangsimplementierung gespeichert werden und nicht wie bei einem permanenten Dienst erst nach Abschluss der Ausführung.
Der connectionString-Attributwert in PersistenceProviderElement wird auf "WorkflowServiceStore" festgelegt. Dabei handelt es sich um den Namen der Verbindungszeichenfolge, die beim Versuch, eine Verbindung zur SQL-Datenbank herzustellen, verwendet wird.
Tipp
In diesem Lernprogramm wird die Datenbank NetFx35Samples_ServicesWorkflowStore verwendet. Führen Sie zum Erstellen der Datenbank das Skript Createstores.cmd von One-Time Setup Procedure for the Windows Communication Foundation Samples aus.
Erstellen Sie den Dienst, und führen Sie ihn aus. Die Ausführung von WcfSvcHost.exe beginnt, und der Dienst wird von diesem Tool gehostet. WcfSvcHost.exe ist ein Entwicklertool, das zu Testzwecken als Host für Dienste fungiert. Zu Testzwecken verwenden die Vorlagen Sequenzielle Workflow-Dienstbibliothek und Statuscomputerworkflow-Dienstbibliothek automatisch die Anwendung WcfSvcHost.exe zum Hosten eines Workflowdiensts, damit Sie nicht selbst eine Hostanwendung erstellen müssen.
Kommentare
Nach dem Erstellen des Workflowdiensts wird in Aufgabe 2: Erstellen eines Workflowdienstclients beschrieben, wie ein Workflowdienstclient erstellt wird, der mit diesem Workflowdienst interagieren kann.
Siehe auch
Aufgaben
Aufgabe 2: Erstellen eines Workflowdienstclients
Konzepte
Gewusst wie: Konfigurieren eines Workflowdiensts
Weitere Ressourcen
Übung 1: Erstellen eines grundlegenden Workflowdiensts
Copyright © 2007 Microsoft Corporation. Alle Rechte vorbehalten.