Instrukcje: aktualizowanie definicji uruchomionego wystąpienia przepływu pracy
Aktualizacja dynamiczna udostępnia mechanizm dla deweloperów aplikacji przepływu pracy w celu zaktualizowania definicji przepływu pracy utrwalonego wystąpienia przepływu pracy. Wymaganą zmianą może być zaimplementowanie poprawki błędów, nowych wymagań lub uwzględnienia nieoczekiwanych zmian. W tym kroku w samouczku pokazano, jak używać aktualizacji dynamicznej do modyfikowania utrwalonego wystąpienia v1
przepływu pracy zgadywania liczb w celu dopasowania do nowych funkcji wprowadzonych w temacie Instrukcje: hostowanie wielu wersji przepływu pracy obok siebie.
Aby utworzyć projekt CreateUpdateMaps
Kliknij prawym przyciskiem myszy pozycję WF45GettingStartedTutorial w Eksplorator rozwiązań i wybierz polecenie Dodaj nowy projekt.
W węźle Zainstalowany wybierz pozycję Visual C#, Windows (lub Visual Basic, Windows).
Uwaga
W zależności od tego, który język programowania jest skonfigurowany jako język podstawowy w programie Visual Studio, węzeł Visual C# lub Visual Basic może znajdować się w węźle Inne języki w węźle Zainstalowane .
Upewnij się, że program .NET Framework 4.5 został wybrany na liście rozwijanej Wersja programu .NET Framework. Wybierz pozycję Aplikacja konsolowa z listy systemu Windows . Wpisz CreateUpdateMaps w polu Nazwa i kliknij przycisk OK.
Kliknij prawym przyciskiem myszy pozycję CreateUpdateMaps w Eksplorator rozwiązań i wybierz polecenie Dodaj odwołanie.
Wybierz pozycję Struktura z węzła Zestawy na liście Dodaj odwołanie . Wpisz Ciąg System.Activities w polu Wyszukaj zestawy , aby filtrować zestawy i ułatwić wybór żądanych odwołań.
Zaznacz pole wyboru obok pozycji System.Activities z listy Wyniki wyszukiwania.
Wpisz serializacji w polu Wyszukaj zestawy i zaznacz pole wyboru obok pozycji System.Runtime.Serialization z listy Wyniki wyszukiwania.
Wpisz Ciąg System.Xaml w polu Wyszukaj zestawy i zaznacz pole wyboru obok pozycji System.Xaml z listy Wyniki wyszukiwania.
Kliknij przycisk OK , aby zamknąć Menedżera odwołań i dodać odwołania.
Dodaj następujące
using
instrukcje (lubImports
) w górnej części pliku z innymiusing
instrukcjami (lubImports
).Imports System.Activities Imports System.Activities.Statements Imports System.Xaml Imports System.Reflection Imports System.IO Imports System.Activities.XamlIntegration Imports System.Activities.DynamicUpdate Imports System.Runtime.Serialization Imports Microsoft.VisualBasic.Activities
using System.Activities; using System.Activities.Statements; using System.IO; using System.Xaml; using System.Reflection; using System.Activities.XamlIntegration; using System.Activities.DynamicUpdate; using System.Runtime.Serialization; using Microsoft.CSharp.Activities;
Dodaj następujące dwa składowe ciągu do
Program
klasy (lubModule1
).Const mapPath = "..\..\..\PreviousVersions" Const definitionPath = "..\..\..\NumberGuessWorkflowActivities_du"
const string mapPath = @"..\..\..\PreviousVersions"; const string definitionPath = @"..\..\..\NumberGuessWorkflowActivities_du";
Dodaj następującą
StartUpdate
metodę doProgram
klasy (lubModule1
). Ta metoda ładuje określoną definicję przepływu pracy xaml do elementu , a następnie wywołuje metodęActivityBuilder
DynamicUpdate.PrepareForUpdate
.PrepareForUpdate
Tworzy kopię definicji przepływu pracy wewnątrzActivityBuilder
elementu . Po zmodyfikowaniu definicji przepływu pracy ta kopia jest używana wraz ze zmodyfikowaną definicją przepływu pracy w celu utworzenia mapy aktualizacji.Private Function StartUpdate(name As String) As ActivityBuilder 'Create the XamlXmlReaderSettings. Dim readerSettings As XamlReaderSettings = New XamlXmlReaderSettings() 'In the XAML the "local" namespace refers to artifacts that come from 'the same project as the XAML. When loading XAML if the currently executing 'assembly is not the same assembly that was referred to as "local" in the XAML 'LocalAssembly must be set to the assembly containing the artifacts. 'Assembly.LoadFile requires an absolute path so convert this relative path 'to an absolute path. readerSettings.LocalAssembly = Assembly.LoadFile( Path.GetFullPath(Path.Combine(mapPath, "NumberGuessWorkflowActivities_v1.dll"))) Dim fullPath As String = Path.Combine(definitionPath, name) Dim xamlReader As XamlXmlReader = New XamlXmlReader(fullPath, readerSettings) 'Load the workflow definition into an ActivityBuilder. Dim wf As ActivityBuilder = XamlServices.Load( ActivityXamlServices.CreateBuilderReader(xamlReader)) 'PrepareForUpdate makes a copy of the workflow definition in the 'ActivityBuilder that is used for comparison when the update 'map is created. DynamicUpdateServices.PrepareForUpdate(wf) Return wf End Function
private static ActivityBuilder StartUpdate(string name) { // Create the XamlXmlReaderSettings. XamlXmlReaderSettings readerSettings = new XamlXmlReaderSettings() { // In the XAML the "local" namespace refers to artifacts that come from // the same project as the XAML. When loading XAML if the currently executing // assembly is not the same assembly that was referred to as "local" in the XAML // LocalAssembly must be set to the assembly containing the artifacts. // Assembly.LoadFile requires an absolute path so convert this relative path // to an absolute path. LocalAssembly = Assembly.LoadFile( Path.GetFullPath(Path.Combine(mapPath, "NumberGuessWorkflowActivities_v1.dll"))) }; string path = Path.Combine(definitionPath, name); XamlXmlReader xamlReader = new XamlXmlReader(path, readerSettings); // Load the workflow definition into an ActivityBuilder. ActivityBuilder wf = XamlServices.Load( ActivityXamlServices.CreateBuilderReader(xamlReader)) as ActivityBuilder; // PrepareForUpdate makes a copy of the workflow definition in the // ActivityBuilder that is used for comparison when the update // map is created. DynamicUpdateServices.PrepareForUpdate(wf); return wf; }
Następnie dodaj następujący kod
CreateUpdateMethod
doProgram
klasy (lubModule1
). Spowoduje to utworzenie dynamicznej mapy aktualizacji przez wywołanie metody DynamicUpdateServices.CreateUpdateMap, a następnie zapisanie mapy aktualizacji przy użyciu określonej nazwy. Ta mapa aktualizacji zawiera informacje wymagane przez środowisko uruchomieniowe przepływu pracy w celu zaktualizowania utrwalonego wystąpienia przepływu pracy, które zostało uruchomione przy użyciu oryginalnej definicji przepływu pracy zawartej wActivityBuilder
pliku , tak aby zakończyło się przy użyciu zaktualizowanej definicji przepływu pracy.Private Sub CreateUpdateMaps(wf As ActivityBuilder, name As String) 'Create the UpdateMap. Dim map As DynamicUpdateMap = DynamicUpdateServices.CreateUpdateMap(wf) 'Serialize it to a file. Dim mapFullPath As String = Path.Combine(mapPath, name) Dim sz As DataContractSerializer = New DataContractSerializer(GetType(DynamicUpdateMap)) Using fs As FileStream = File.Open(mapFullPath, FileMode.Create) sz.WriteObject(fs, map) End Using End Sub
private static void CreateUpdateMaps(ActivityBuilder wf, string name) { // Create the UpdateMap. DynamicUpdateMap map = DynamicUpdateServices.CreateUpdateMap(wf); // Serialize it to a file. string path = Path.Combine(mapPath, name); DataContractSerializer sz = new DataContractSerializer(typeof(DynamicUpdateMap)); using (FileStream fs = System.IO.File.Open(path, FileMode.Create)) { sz.WriteObject(fs, map); } }
Dodaj następującą
SaveUpdatedDefinition
metodę doProgram
klasy (lubModule1
). Ta metoda zapisuje zaktualizowaną definicję przepływu pracy po utworzeniu mapy aktualizacji.Private Sub SaveUpdatedDefinition(wf As ActivityBuilder, name As String) Dim xamlPath As String = Path.Combine(definitionPath, name) Dim sw As StreamWriter = File.CreateText(xamlPath) Dim xw As XamlWriter = ActivityXamlServices.CreateBuilderWriter( New XamlXmlWriter(sw, New XamlSchemaContext())) XamlServices.Save(xw, wf) sw.Close() End Sub
private static void SaveUpdatedDefinition(ActivityBuilder wf, string name) { string xamlPath = Path.Combine(definitionPath, name); StreamWriter sw = File.CreateText(xamlPath); XamlWriter xw = ActivityXamlServices.CreateBuilderWriter( new XamlXmlWriter(sw, new XamlSchemaContext())); XamlServices.Save(xw, wf); sw.Close(); }
Aby zaktualizować StateMachineNumberGuessWorkflow
Dodaj element
CreateStateMachineUpdateMap
doProgram
klasy (lubModule1
).Private Sub CreateStateMachineUpdateMap() End Sub
private static void CreateStateMachineUpdateMap() { }
Wywołaj metodę
StartUpdate
, a następnie uzyskaj odwołanie do działania głównegoStateMachine
przepływu pracy.Dim wf As ActivityBuilder = StartUpdate("StateMachineNumberGuessWorkflow.xaml") 'Get a reference to the root StateMachine activity. Dim sm As StateMachine = wf.Implementation
ActivityBuilder wf = StartUpdate("StateMachineNumberGuessWorkflow.xaml"); // Get a reference to the root StateMachine activity. StateMachine sm = wf.Implementation as StateMachine;
Następnie zaktualizuj wyrażenia dwóch
WriteLine
działań, które wyświetlają, czy odgadnięcie użytkownika jest zbyt wysokie, czy zbyt niskie, tak aby były zgodne z aktualizacjami w temacie Instrukcje: hostowanie wielu wersji przepływu pracy obok siebie.'Update the Text of the two WriteLine activities that write the 'results of the user's guess. They are contained in the workflow as the 'Then and Else action of the If activity in sm.States[1].Transitions[1].Action. Dim guessLow As Statements.If = sm.States(1).Transitions(1).Action 'Update the "too low" message. Dim tooLow As WriteLine = guessLow.Then tooLow.Text = New VisualBasicValue(Of String)("Guess.ToString() & "" is too low.""") 'Update the "too high" message. Dim tooHigh As WriteLine = guessLow.Else tooHigh.Text = New VisualBasicValue(Of String)("Guess.ToString() & "" is too high.""")
// Update the Text of the two WriteLine activities that write the // results of the user's guess. They are contained in the workflow as the // Then and Else action of the If activity in sm.States[1].Transitions[1].Action. If guessLow = sm.States[1].Transitions[1].Action as If; // Update the "too low" message. WriteLine tooLow = guessLow.Then as WriteLine; tooLow.Text = new CSharpValue<string>("Guess.ToString() + \" is too low.\""); // Update the "too high" message. WriteLine tooHigh = guessLow.Else as WriteLine; tooHigh.Text = new CSharpValue<string>("Guess.ToString() + \" is too high.\"");
Następnie dodaj nowe
WriteLine
działanie, które wyświetla komunikat zamykający.'Create the new WriteLine that displays the closing message. Dim wl As New WriteLine() With { .Text = New VisualBasicValue(Of String) _ ("Guess.ToString() + "" is correct. You guessed it in "" & Turns.ToString() & "" turns.""") } 'Add it as the Action for the Guess Correct transition. The Guess Correct 'transition is the first transition of States[1]. The transitions are listed 'at the bottom of the State activity designer. sm.States(1).Transitions(0).Action = wl
// Create the new WriteLine that displays the closing message. WriteLine wl = new WriteLine { Text = new CSharpValue<string>("Guess.ToString() + \" is correct. You guessed it in \" + Turns.ToString() + \" turns.\"") }; // Add it as the Action for the Guess Correct transition. The Guess Correct // transition is the first transition of States[1]. The transitions are listed // at the bottom of the State activity designer. sm.States[1].Transitions[0].Action = wl;
Po zaktualizowaniu przepływu pracy wywołaj metodę
CreateUpdateMaps
iSaveUpdatedDefinition
.CreateUpdateMaps
program tworzy i zapisujeDynamicUpdateMap
SaveUpdatedDefinition
zaktualizowaną definicję przepływu pracy.'Create the update map. CreateUpdateMaps(wf, "StateMachineNumberGuessWorkflow.map") 'Save the updated workflow definition. SaveUpdatedDefinition(wf, "StateMachineNumberGuessWorkflow_du.xaml")
// Create the update map. CreateUpdateMaps(wf, "StateMachineNumberGuessWorkflow.map"); // Save the updated workflow definition. SaveUpdatedDefinition(wf, "StateMachineNumberGuessWorkflow_du.xaml");
Poniższy przykład to ukończona
CreateStateMachineUpdateMap
metoda.Private Sub CreateStateMachineUpdateMap() Dim wf As ActivityBuilder = StartUpdate("StateMachineNumberGuessWorkflow.xaml") 'Get a reference to the root StateMachine activity. Dim sm As StateMachine = wf.Implementation 'Update the Text of the two WriteLine activities that write the 'results of the user's guess. They are contained in the workflow as the 'Then and Else action of the If activity in sm.States[1].Transitions[1].Action. Dim guessLow As Statements.If = sm.States(1).Transitions(1).Action 'Update the "too low" message. Dim tooLow As WriteLine = guessLow.Then tooLow.Text = New VisualBasicValue(Of String)("Guess.ToString() & "" is too low.""") 'Update the "too high" message. Dim tooHigh As WriteLine = guessLow.Else tooHigh.Text = New VisualBasicValue(Of String)("Guess.ToString() & "" is too high.""") 'Create the new WriteLine that displays the closing message. Dim wl As New WriteLine() With { .Text = New VisualBasicValue(Of String) _ ("Guess.ToString() + "" is correct. You guessed it in "" & Turns.ToString() & "" turns.""") } 'Add it as the Action for the Guess Correct transition. The Guess Correct 'transition is the first transition of States[1]. The transitions are listed 'at the bottom of the State activity designer. sm.States(1).Transitions(0).Action = wl 'Create the update map. CreateUpdateMaps(wf, "StateMachineNumberGuessWorkflow.map") 'Save the updated workflow definition. SaveUpdatedDefinition(wf, "StateMachineNumberGuessWorkflow_du.xaml") End Sub
private static void CreateStateMachineUpdateMap() { ActivityBuilder wf = StartUpdate("StateMachineNumberGuessWorkflow.xaml"); // Get a reference to the root StateMachine activity. StateMachine sm = wf.Implementation as StateMachine; // Update the Text of the two WriteLine activities that write the // results of the user's guess. They are contained in the workflow as the // Then and Else action of the If activity in sm.States[1].Transitions[1].Action. If guessLow = sm.States[1].Transitions[1].Action as If; // Update the "too low" message. WriteLine tooLow = guessLow.Then as WriteLine; tooLow.Text = new CSharpValue<string>("Guess.ToString() + \" is too low.\""); // Update the "too high" message. WriteLine tooHigh = guessLow.Else as WriteLine; tooHigh.Text = new CSharpValue<string>("Guess.ToString() + \" is too high.\""); // Create the new WriteLine that displays the closing message. WriteLine wl = new WriteLine { Text = new CSharpValue<string>("Guess.ToString() + \" is correct. You guessed it in \" + Turns.ToString() + \" turns.\"") }; // Add it as the Action for the Guess Correct transition. The Guess Correct // transition is the first transition of States[1]. The transitions are listed // at the bottom of the State activity designer. sm.States[1].Transitions[0].Action = wl; // Create the update map. CreateUpdateMaps(wf, "StateMachineNumberGuessWorkflow.map"); // Save the updated workflow definition. SaveUpdatedDefinition(wf, "StateMachineNumberGuessWorkflow_du.xaml"); }
Aby zaktualizować schemat blokowyNumberGuessWorkflow
Dodaj następujący kod
CreateFlowchartUpdateMethod
doProgram
klasy (lubModule1
). Ta metoda jest podobna doCreateStateMachineUpdateMap
metody . Rozpoczyna się od wywołania metodyStartUpdate
, aktualizuje definicję przepływu pracy schematu blokowego i kończy się, zapisując mapę aktualizacji i zaktualizowaną definicję przepływu pracy.Private Sub CreateFlowchartUpdateMap() Dim wf As ActivityBuilder = StartUpdate("FlowchartNumberGuessWorkflow.xaml") 'Get a reference to the root Flowchart activity. Dim fc As Flowchart = wf.Implementation 'Update the Text of the two WriteLine activities that write the 'results of the user's guess. They are contained in the workflow as the 'True and False action of the "Guess < Target" FlowDecision, which is 'Nodes[4]. Dim guessLow As FlowDecision = fc.Nodes(4) 'Update the "too low" message. Dim trueStep As FlowStep = guessLow.True Dim tooLow As WriteLine = trueStep.Action tooLow.Text = New VisualBasicValue(Of String)("Guess.ToString() & "" is too low.""") 'Update the "too high" message. Dim falseStep As FlowStep = guessLow.False Dim tooHigh As WriteLine = falseStep.Action tooHigh.Text = New VisualBasicValue(Of String)("Guess.ToString() & "" is too high.""") 'Create the new WriteLine that displays the closing message. Dim wl As New WriteLine() With { .Text = New VisualBasicValue(Of String) _ ("Guess.ToString() + "" is correct. You guessed it in "" & Turns.ToString() & "" turns.""") } 'Create a FlowStep to hold the WriteLine. Dim closingStep As New FlowStep() With { .Action = wl } 'Add this new FlowStep to the True action of the '"Guess = Guess" FlowDecision Dim guessCorrect As FlowDecision = fc.Nodes(3) guessCorrect.True = closingStep 'Add the new FlowStep to the Nodes collection. 'If closingStep was replacing an existing node then 'we would need to remove that Step from the collection. 'In this example there was no existing True step to remove. fc.Nodes.Add(closingStep) 'Create the update map. CreateUpdateMaps(wf, "FlowchartNumberGuessWorkflow.map") 'Save the updated workflow definition. SaveUpdatedDefinition(wf, "FlowchartNumberGuessWorkflow_du.xaml") End Sub
private static void CreateFlowchartUpdateMap() { ActivityBuilder wf = StartUpdate("FlowchartNumberGuessWorkflow.xaml"); // Get a reference to the root Flowchart activity. Flowchart fc = wf.Implementation as Flowchart; // Update the Text of the two WriteLine activities that write the // results of the user's guess. They are contained in the workflow as the // True and False action of the "Guess < Target" FlowDecision, which is // Nodes[4]. FlowDecision guessLow = fc.Nodes[4] as FlowDecision; // Update the "too low" message. FlowStep trueStep = guessLow.True as FlowStep; WriteLine tooLow = trueStep.Action as WriteLine; tooLow.Text = new CSharpValue<string>("Guess.ToString() + \" is too low.\""); // Update the "too high" message. FlowStep falseStep = guessLow.False as FlowStep; WriteLine tooHigh = falseStep.Action as WriteLine; tooHigh.Text = new CSharpValue<string>("Guess.ToString() + \" is too high.\""); // Add the new WriteLine that displays the closing message. WriteLine wl = new WriteLine { Text = new CSharpValue<string>("Guess.ToString() + \" is correct. You guessed it in \" + Turns.ToString() + \" turns.\"") }; // Create a FlowStep to hold the WriteLine. FlowStep closingStep = new FlowStep { Action = wl }; // Add this new FlowStep to the True action of the // "Guess == Guess" FlowDecision FlowDecision guessCorrect = fc.Nodes[3] as FlowDecision; guessCorrect.True = closingStep; // Add the new FlowStep to the Nodes collection. // If closingStep was replacing an existing node then // we would need to remove that Step from the collection. // In this example there was no existing True step to remove. fc.Nodes.Add(closingStep); // Create the update map. CreateUpdateMaps(wf, "FlowchartNumberGuessWorkflow.map"); // Save the updated workflow definition. SaveUpdatedDefinition(wf, "FlowchartNumberGuessWorkflow_du.xaml"); }
Aby zaktualizować sekwencyjneNumberGuessWorkflow
Dodaj następujący kod
CreateSequentialUpdateMethod
doProgram
klasy (lubModule1
). Ta metoda jest podobna do pozostałych dwóch metod. Rozpoczyna się od wywołania metodyStartUpdate
, aktualizuje sekwencyjną definicję przepływu pracy i kończy się, zapisując mapę aktualizacji i zaktualizowaną definicję przepływu pracy.Private Sub CreateSequentialUpdateMap() Dim wf As ActivityBuilder = StartUpdate("SequentialNumberGuessWorkflow.xaml") 'Get a reference to the root activity in the workflow. Dim rootSequence As Sequence = wf.Implementation 'Update the Text of the two WriteLine activities that write the 'results of the user's guess. They are contained in the workflow as the 'Then and Else action of the "Guess < Target" If activity. 'Sequence[1]->DoWhile->Body->Sequence[2]->If->Then->If Dim gameLoop As Statements.DoWhile = rootSequence.Activities(1) Dim gameBody As Sequence = gameLoop.Body Dim guessCorrect As Statements.If = gameBody.Activities(2) Dim guessLow As Statements.If = guessCorrect.Then Dim tooLow As WriteLine = guessLow.Then tooLow.Text = New VisualBasicValue(Of String)("Guess.ToString() & "" is too low.""") Dim tooHigh As WriteLine = guessLow.Else tooHigh.Text = New VisualBasicValue(Of String)("Guess.ToString() & "" is too high.""") 'Create the new WriteLine that displays the closing message. Dim wl As New WriteLine() With { .Text = New VisualBasicValue(Of String) _ ("Guess.ToString() + "" is correct. You guessed it in "" & Turns.ToString() & "" turns.""") } 'Insert it as the third activity in the root sequence rootSequence.Activities.Insert(2, wl) 'Create the update map. CreateUpdateMaps(wf, "SequentialNumberGuessWorkflow.map") 'Save the updated workflow definition. SaveUpdatedDefinition(wf, "SequentialNumberGuessWorkflow_du.xaml") End Sub
private static void CreateSequentialUpdateMap() { ActivityBuilder wf = StartUpdate("SequentialNumberGuessWorkflow.xaml"); // Get a reference to the root activity in the workflow. Sequence rootSequence = wf.Implementation as Sequence; // Update the Text of the two WriteLine activities that write the // results of the user's guess. They are contained in the workflow as the // Then and Else action of the "Guess < Target" If activity. // Sequence[1]->DoWhile->Body->Sequence[2]->If->Then->If DoWhile gameLoop = rootSequence.Activities[1] as DoWhile; Sequence gameBody = gameLoop.Body as Sequence; If guessCorrect = gameBody.Activities[2] as If; If guessLow = guessCorrect.Then as If; WriteLine tooLow = guessLow.Then as WriteLine; tooLow.Text = new CSharpValue<string>("Guess.ToString() + \" is too low.\""); WriteLine tooHigh = guessLow.Else as WriteLine; tooHigh.Text = new CSharpValue<string>("Guess.ToString() + \" is too high.\""); // Add the new WriteLine that displays the closing message. WriteLine wl = new WriteLine { Text = new CSharpValue<string>("Guess.ToString() + \" is correct. You guessed it in \" + Turns.ToString() + \" turns.\"") }; // Insert it as the third activity in the root sequence rootSequence.Activities.Insert(2, wl); // Create the update map. CreateUpdateMaps(wf, "SequentialNumberGuessWorkflow.map"); // Save the updated workflow definition. SaveUpdatedDefinition(wf, "SequentialNumberGuessWorkflow_du.xaml"); }
Aby skompilować i uruchomić aplikację CreateUpdateMaps
Zaktualizuj metodę
Main
i dodaj następujące trzy wywołania metody. Te metody są dodawane w poniższych sekcjach. Każda metoda aktualizuje odpowiedni przepływ pracy odgadnięcia liczb i tworzy elementDynamicUpdateMap
opisujący aktualizacje.Sub Main() 'Create the update maps for the changes needed to the v1 activities 'so they match the v2 activities. CreateSequentialUpdateMap() CreateFlowchartUpdateMap() CreateStateMachineUpdateMap() End Sub
static void Main(string[] args) { // Create the update maps for the changes needed to the v1 activities // so they match the v2 activities. CreateSequentialUpdateMap(); CreateFlowchartUpdateMap(); CreateStateMachineUpdateMap(); }
Kliknij prawym przyciskiem myszy pozycję CreateUpdateMaps w Eksplorator rozwiązań i wybierz polecenie Ustaw jako projekt startowy.
Naciśnij CTRL+SHIFT+B, aby skompilować rozwiązanie, a następnie naciśnij CTRL+F5, aby uruchomić aplikację
CreateUpdateMaps
.Uwaga
Aplikacja
CreateUpdateMaps
nie wyświetla żadnych informacji o stanie podczas działania, ale jeśli spojrzysz na folder NumberGuessWorkflowActivities_du i folder PreviousVersions , zobaczysz zaktualizowane pliki definicji przepływu pracy i mapy aktualizacji.Po utworzeniu map aktualizacji i zaktualizowaniu definicji przepływu pracy następnym krokiem jest utworzenie zaktualizowanego zestawu przepływu pracy zawierającego zaktualizowane definicje.
Aby skompilować zaktualizowany zestaw przepływu pracy
Otwórz drugie wystąpienie programu Visual Studio 2012.
Wybierz pozycję Otwórz, Projekt/Rozwiązanie z menu Plik .
Przejdź do folderu NumberGuessWorkflowActivities_du utworzonego w temacie Instrukcje: hostowanie wielu wersji przepływu pracy obok siebie, wybierz kolejno pozycje NumberGuessWorkflowActivities.csproj (lub vbproj), a następnie kliknij przycisk Otwórz.
W Eksplorator rozwiązań kliknij prawym przyciskiem myszy pozycję SekwencyjneNumberGuessWorkflow.xaml i wybierz polecenie Wyklucz z projektu. Zrób to samo w przypadku schematu blokowegoNumberGuessWorkflow.xaml i StateMachineNumberGuessWorkflow.xaml. Ten krok usuwa poprzednie wersje definicji przepływu pracy z projektu.
Wybierz pozycję Dodaj istniejący element z menu Projekt .
Przejdź do folderu NumberGuessWorkflowActivities_du utworzonego w temacie Instrukcje: hostowanie wielu wersji przepływu pracy obok siebie.
Wybierz pozycję Pliki XAML (*.xaml;*.xoml) z listy rozwijanej Pliki typu .
Wybierz pozycję SequentialNumberGuessWorkflow_du.xaml, FlowchartNumberGuessWorkflow_du.xaml i StateMachineNumberGuessWorkflow_du.xaml, a następnie kliknij przycisk Dodaj.
Uwaga
CTRL +Kliknij, aby wybrać wiele elementów jednocześnie.
Ten krok dodaje zaktualizowane wersje definicji przepływu pracy do projektu.
Naciśnij kombinację klawiszy CTRL+SHIFT+B. Projekt zostanie skompilowany.
Wybierz pozycję Zamknij rozwiązanie z menu Plik . Plik rozwiązania dla projektu nie jest wymagany, dlatego kliknij przycisk Nie , aby zamknąć program Visual Studio bez zapisywania pliku rozwiązania. Wybierz pozycję Zakończ z menu Plik , aby zamknąć program Visual Studio.
Otwórz Eksploratora Windows i przejdź do folderu NumberGuessWorkflowActivities_du\bin\Debug (lub bin\Release w zależności od ustawień projektu).
Zmień nazwę NumberGuessWorkflowActivities.dll na NumberGuessWorkflowActivities_v15.dll i skopiuj ją do folderu PreviousVersions utworzonego w temacie Instrukcje: hostowanie wielu wersji przepływu pracy obok siebie.
Aby zaktualizować element WorkflowVersionMap przy użyciu nowych wersji
Wróć do początkowego wystąpienia programu Visual Studio 2012.
Kliknij dwukrotnie WorkflowVersionMap.cs (lub WorkflowVersionMap.vb) w projekcie NumberGuessWorkflowHost , aby go otworzyć.
Dodaj trzy nowe tożsamości przepływu pracy tuż poniżej sześciu istniejących deklaracji tożsamości przepływu pracy. W tym samouczku
1.5.0.0
jest używany jakoWorkflowIdentity.Version
element tożsamości aktualizacji dynamicznej. Te nowev15
tożsamości przepływu pracy będą używane w celu zapewnienia prawidłowej definicji przepływu pracy dla dynamicznie aktualizowanych wystąpień utrwalonego przepływu pracy.'Current version identities. Public StateMachineNumberGuessIdentity As WorkflowIdentity Public FlowchartNumberGuessIdentity As WorkflowIdentity Public SequentialNumberGuessIdentity As WorkflowIdentity 'v1 identities. Public StateMachineNumberGuessIdentity_v1 As WorkflowIdentity Public FlowchartNumberGuessIdentity_v1 As WorkflowIdentity Public SequentialNumberGuessIdentity_v1 As WorkflowIdentity 'v1.5 (Dynamic Update) identities. Public StateMachineNumberGuessIdentity_v15 As WorkflowIdentity Public FlowchartNumberGuessIdentity_v15 As WorkflowIdentity Public SequentialNumberGuessIdentity_v15 As WorkflowIdentity
// Current version identities. static public WorkflowIdentity StateMachineNumberGuessIdentity; static public WorkflowIdentity FlowchartNumberGuessIdentity; static public WorkflowIdentity SequentialNumberGuessIdentity; // v1 identities. static public WorkflowIdentity StateMachineNumberGuessIdentity_v1; static public WorkflowIdentity FlowchartNumberGuessIdentity_v1; static public WorkflowIdentity SequentialNumberGuessIdentity_v1; // v1.5 (Dynamic Update) identities. static public WorkflowIdentity StateMachineNumberGuessIdentity_v15; static public WorkflowIdentity FlowchartNumberGuessIdentity_v15; static public WorkflowIdentity SequentialNumberGuessIdentity_v15;
Dodaj następujący kod na końcu konstruktora. Ten kod inicjuje tożsamości przepływu pracy aktualizacji dynamicznej, ładuje odpowiednie definicje przepływu pracy i dodaje je do słownika wersji przepływu pracy.
'Initialize the dynamic update workflow identities. StateMachineNumberGuessIdentity_v15 = New WorkflowIdentity With { .Name = "StateMachineNumberGuessWorkflow", .Version = New Version(1, 5, 0, 0) } FlowchartNumberGuessIdentity_v15 = New WorkflowIdentity With { .Name = "FlowchartNumberGuessWorkflow", .Version = New Version(1, 5, 0, 0) } SequentialNumberGuessIdentity_v15 = New WorkflowIdentity With { .Name = "SequentialNumberGuessWorkflow", .Version = New Version(1, 5, 0, 0) } 'Add the dynamic update workflow identities to the dictionary along with 'the corresponding workflow definitions loaded from the v15 assembly. 'Assembly.LoadFile requires an absolute path so convert this relative path 'to an absolute path. Dim v15AssemblyPath As String = "..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v15.dll" v15AssemblyPath = Path.GetFullPath(v15AssemblyPath) Dim v15Assembly As Assembly = Assembly.LoadFile(v15AssemblyPath) map.Add(StateMachineNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow")) map.Add(SequentialNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow")) map.Add(FlowchartNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow"))
// Initialize the dynamic update workflow identities. StateMachineNumberGuessIdentity_v15 = new WorkflowIdentity { Name = "StateMachineNumberGuessWorkflow", Version = new Version(1, 5, 0, 0) }; FlowchartNumberGuessIdentity_v15 = new WorkflowIdentity { Name = "FlowchartNumberGuessWorkflow", Version = new Version(1, 5, 0, 0) }; SequentialNumberGuessIdentity_v15 = new WorkflowIdentity { Name = "SequentialNumberGuessWorkflow", Version = new Version(1, 5, 0, 0) }; // Add the dynamic update workflow identities to the dictionary along with // the corresponding workflow definitions loaded from the v15 assembly. // Assembly.LoadFile requires an absolute path so convert this relative path // to an absolute path. string v15AssemblyPath = @"..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v15.dll"; v15AssemblyPath = Path.GetFullPath(v15AssemblyPath); Assembly v15Assembly = Assembly.LoadFile(v15AssemblyPath); map.Add(StateMachineNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow") as Activity); map.Add(SequentialNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow") as Activity); map.Add(FlowchartNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow") as Activity);
Poniższy przykład to ukończona
WorkflowVersionMap
klasa.Public Module WorkflowVersionMap Dim map As Dictionary(Of WorkflowIdentity, Activity) 'Current version identities. Public StateMachineNumberGuessIdentity As WorkflowIdentity Public FlowchartNumberGuessIdentity As WorkflowIdentity Public SequentialNumberGuessIdentity As WorkflowIdentity 'v1 identities. Public StateMachineNumberGuessIdentity_v1 As WorkflowIdentity Public FlowchartNumberGuessIdentity_v1 As WorkflowIdentity Public SequentialNumberGuessIdentity_v1 As WorkflowIdentity 'v1.5 (Dynamic Update) identities. Public StateMachineNumberGuessIdentity_v15 As WorkflowIdentity Public FlowchartNumberGuessIdentity_v15 As WorkflowIdentity Public SequentialNumberGuessIdentity_v15 As WorkflowIdentity Sub New() map = New Dictionary(Of WorkflowIdentity, Activity) 'Add the current workflow version identities. StateMachineNumberGuessIdentity = New WorkflowIdentity With { .Name = "StateMachineNumberGuessWorkflow", .Version = New Version(2, 0, 0, 0) } FlowchartNumberGuessIdentity = New WorkflowIdentity With { .Name = "FlowchartNumberGuessWorkflow", .Version = New Version(2, 0, 0, 0) } SequentialNumberGuessIdentity = New WorkflowIdentity With { .Name = "SequentialNumberGuessWorkflow", .Version = New Version(2, 0, 0, 0) } map.Add(StateMachineNumberGuessIdentity, New StateMachineNumberGuessWorkflow()) map.Add(FlowchartNumberGuessIdentity, New FlowchartNumberGuessWorkflow()) map.Add(SequentialNumberGuessIdentity, New SequentialNumberGuessWorkflow()) 'Initialize the previous workflow version identities. StateMachineNumberGuessIdentity_v1 = New WorkflowIdentity With { .Name = "StateMachineNumberGuessWorkflow", .Version = New Version(1, 0, 0, 0) } FlowchartNumberGuessIdentity_v1 = New WorkflowIdentity With { .Name = "FlowchartNumberGuessWorkflow", .Version = New Version(1, 0, 0, 0) } SequentialNumberGuessIdentity_v1 = New WorkflowIdentity With { .Name = "SequentialNumberGuessWorkflow", .Version = New Version(1, 0, 0, 0) } 'Add the previous version workflow identities to the dictionary along with 'the corresponding workflow definitions loaded from the v1 assembly. 'Assembly.LoadFile requires an absolute path so convert this relative path 'to an absolute path. Dim v1AssemblyPath As String = "..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v1.dll" v1AssemblyPath = Path.GetFullPath(v1AssemblyPath) Dim v1Assembly As Assembly = Assembly.LoadFile(v1AssemblyPath) map.Add(StateMachineNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow")) map.Add(SequentialNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow")) map.Add(FlowchartNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow")) 'Initialize the dynamic update workflow identities. StateMachineNumberGuessIdentity_v15 = New WorkflowIdentity With { .Name = "StateMachineNumberGuessWorkflow", .Version = New Version(1, 5, 0, 0) } FlowchartNumberGuessIdentity_v15 = New WorkflowIdentity With { .Name = "FlowchartNumberGuessWorkflow", .Version = New Version(1, 5, 0, 0) } SequentialNumberGuessIdentity_v15 = New WorkflowIdentity With { .Name = "SequentialNumberGuessWorkflow", .Version = New Version(1, 5, 0, 0) } 'Add the dynamic update workflow identities to the dictionary along with 'the corresponding workflow definitions loaded from the v15 assembly. 'Assembly.LoadFile requires an absolute path so convert this relative path 'to an absolute path. Dim v15AssemblyPath As String = "..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v15.dll" v15AssemblyPath = Path.GetFullPath(v15AssemblyPath) Dim v15Assembly As Assembly = Assembly.LoadFile(v15AssemblyPath) map.Add(StateMachineNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow")) map.Add(SequentialNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow")) map.Add(FlowchartNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow")) End Sub Public Function GetWorkflowDefinition(identity As WorkflowIdentity) As Activity Return map(identity) End Function Public Function GetIdentityDescription(identity As WorkflowIdentity) As String Return identity.ToString() End Function End Module
public static class WorkflowVersionMap { static Dictionary<WorkflowIdentity, Activity> map; // Current version identities. static public WorkflowIdentity StateMachineNumberGuessIdentity; static public WorkflowIdentity FlowchartNumberGuessIdentity; static public WorkflowIdentity SequentialNumberGuessIdentity; // v1 identities. static public WorkflowIdentity StateMachineNumberGuessIdentity_v1; static public WorkflowIdentity FlowchartNumberGuessIdentity_v1; static public WorkflowIdentity SequentialNumberGuessIdentity_v1; // v1.5 (Dynamic Update) identities. static public WorkflowIdentity StateMachineNumberGuessIdentity_v15; static public WorkflowIdentity FlowchartNumberGuessIdentity_v15; static public WorkflowIdentity SequentialNumberGuessIdentity_v15; static WorkflowVersionMap() { map = new Dictionary<WorkflowIdentity, Activity>(); // Add the current workflow version identities. StateMachineNumberGuessIdentity = new WorkflowIdentity { Name = "StateMachineNumberGuessWorkflow", // Version = new Version(1, 0, 0, 0), Version = new Version(2, 0, 0, 0) }; FlowchartNumberGuessIdentity = new WorkflowIdentity { Name = "FlowchartNumberGuessWorkflow", // Version = new Version(1, 0, 0, 0), Version = new Version(2, 0, 0, 0) }; SequentialNumberGuessIdentity = new WorkflowIdentity { Name = "SequentialNumberGuessWorkflow", // Version = new Version(1, 0, 0, 0), Version = new Version(2, 0, 0, 0) }; map.Add(StateMachineNumberGuessIdentity, new StateMachineNumberGuessWorkflow()); map.Add(FlowchartNumberGuessIdentity, new FlowchartNumberGuessWorkflow()); map.Add(SequentialNumberGuessIdentity, new SequentialNumberGuessWorkflow()); // Initialize the previous workflow version identities. StateMachineNumberGuessIdentity_v1 = new WorkflowIdentity { Name = "StateMachineNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }; FlowchartNumberGuessIdentity_v1 = new WorkflowIdentity { Name = "FlowchartNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }; SequentialNumberGuessIdentity_v1 = new WorkflowIdentity { Name = "SequentialNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }; // Add the previous version workflow identities to the dictionary along with // the corresponding workflow definitions loaded from the v1 assembly. // Assembly.LoadFile requires an absolute path so convert this relative path // to an absolute path. string v1AssemblyPath = @"..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v1.dll"; v1AssemblyPath = Path.GetFullPath(v1AssemblyPath); Assembly v1Assembly = Assembly.LoadFile(v1AssemblyPath); map.Add(StateMachineNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow") as Activity); map.Add(SequentialNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow") as Activity); map.Add(FlowchartNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow") as Activity); // Initialize the dynamic update workflow identities. StateMachineNumberGuessIdentity_v15 = new WorkflowIdentity { Name = "StateMachineNumberGuessWorkflow", Version = new Version(1, 5, 0, 0) }; FlowchartNumberGuessIdentity_v15 = new WorkflowIdentity { Name = "FlowchartNumberGuessWorkflow", Version = new Version(1, 5, 0, 0) }; SequentialNumberGuessIdentity_v15 = new WorkflowIdentity { Name = "SequentialNumberGuessWorkflow", Version = new Version(1, 5, 0, 0) }; // Add the dynamic update workflow identities to the dictionary along with // the corresponding workflow definitions loaded from the v15 assembly. // Assembly.LoadFile requires an absolute path so convert this relative path // to an absolute path. string v15AssemblyPath = @"..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v15.dll"; v15AssemblyPath = Path.GetFullPath(v15AssemblyPath); Assembly v15Assembly = Assembly.LoadFile(v15AssemblyPath); map.Add(StateMachineNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow") as Activity); map.Add(SequentialNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow") as Activity); map.Add(FlowchartNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow") as Activity); } public static Activity GetWorkflowDefinition(WorkflowIdentity identity) { return map[identity]; } public static string GetIdentityDescription(WorkflowIdentity identity) { return identity.ToString(); } }
Naciśnij kombinację klawiszy CTRL+SHIFT+B. Projekt zostanie skompilowany.
Aby zastosować aktualizacje dynamiczne
Kliknij prawym przyciskiem myszy pozycję WF45GettingStartedTutorial w Eksplorator rozwiązań i wybierz polecenie Dodaj nowy projekt.
W węźle Zainstalowany wybierz pozycję Visual C#, Windows (lub Visual Basic, Windows).
Uwaga
W zależności od tego, który język programowania jest skonfigurowany jako język podstawowy w programie Visual Studio, węzeł Visual C# lub Visual Basic może znajdować się w węźle Inne języki w węźle Zainstalowane .
Upewnij się, że program .NET Framework 4.5 został wybrany na liście rozwijanej Wersja programu .NET Framework. Wybierz pozycję Aplikacja konsolowa z listy systemu Windows . Wpisz ApplyDynamicUpdate w polu Nazwa i kliknij przycisk OK.
Kliknij prawym przyciskiem myszy pozycję ApplyDynamicUpdate w Eksplorator rozwiązań i wybierz polecenie Dodaj odwołanie.
Kliknij pozycję Rozwiązanie i zaznacz pole wyboru obok pozycji NumberGuessWorkflowHost. To odwołanie jest potrzebne,
ApplyDynamicUpdate
aby można było użyćNumberGuessWorkflowHost.WorkflowVersionMap
klasy .Wybierz pozycję Struktura z węzła Zestawy na liście Dodaj odwołanie . Wpisz System.Activities w polu Wyszukaj zestawy . Spowoduje to filtrowanie zestawów i ułatwienie wybierania żądanych odwołań.
Zaznacz pole wyboru obok pozycji System.Activities z listy Wyniki wyszukiwania.
Wpisz serializacji w polu Wyszukaj zestawy i zaznacz pole wyboru obok pozycji System.Runtime.Serialization z listy Wyniki wyszukiwania.
Wpisz DurableInstancing w polu Wyszukaj zestawy i zaznacz pole wyboru obok pozycji System.Activities.DurableInstancing i System.Runtime.DurableInstancing z listy Wyniki wyszukiwania.
Kliknij przycisk OK , aby zamknąć Menedżera odwołań i dodać odwołania.
Kliknij prawym przyciskiem myszy pozycję ApplyDynamicUpdate w Eksplorator rozwiązań i wybierz polecenie Dodaj, klasa. Wpisz
DynamicUpdateInfo
w polu Nazwa i kliknij przycisk Dodaj.Dodaj do klasy następujące dwa składowe
DynamicUpdateInfo
. Poniższy przykład to ukończonaDynamicUpdateInfo
klasa. Ta klasa zawiera informacje o mapie aktualizacji i nowej tożsamości przepływu pracy używanej podczas aktualizowania wystąpienia przepływu pracy.Public Class DynamicUpdateInfo Public updateMap As DynamicUpdateMap Public newIdentity As WorkflowIdentity End Class
class DynamicUpdateInfo { public DynamicUpdateMap updateMap; public WorkflowIdentity newIdentity; }
Dodaj następujące
using
instrukcje (lubImports
) w górnej części pliku z innymiusing
instrukcjami (lubImports
).Imports System.Activities Imports System.Activities.DynamicUpdate
using System.Activities; using System.Activities.DynamicUpdate;
Kliknij dwukrotnie Program.cs (lub Module1.vb) w Eksplorator rozwiązań.
Dodaj następujące
using
instrukcje (lubImports
) w górnej części pliku z innymiusing
instrukcjami (lubImports
).Imports NumberGuessWorkflowHost Imports System.Data.SqlClient Imports System.Activities.DynamicUpdate Imports System.IO Imports System.Runtime.Serialization Imports System.Activities Imports System.Activities.DurableInstancing
using NumberGuessWorkflowHost; using System.Data; using System.Data.SqlClient; using System.Activities; using System.Activities.DynamicUpdate; using System.IO; using System.Runtime.Serialization; using System.Activities.DurableInstancing;
Dodaj następujący element członkowski parametry połączenia do
Program
klasy (lubModule1
).Const connectionString = "Server=.\SQLEXPRESS;Initial Catalog=WF45GettingStartedTutorial;Integrated Security=SSPI"
const string connectionString = "Server=.\\SQLEXPRESS;Initial Catalog=WF45GettingStartedTutorial;Integrated Security=SSPI";
Ważne
Firma Microsoft zaleca korzystanie z najbezpieczniejszego dostępnego przepływu uwierzytelniania. Jeśli łączysz się z usługą Azure SQL, tożsamości zarządzane dla zasobów platformy Azure to zalecana metoda uwierzytelniania.
Uwaga
W zależności od wersji programu SQL Server nazwa serwera parametry połączenia może być inna.
Dodaj następującą
GetIDs
metodę doProgram
klasy (lubModule1
). Ta metoda zwraca listę identyfikatorów utrwalonego wystąpienia przepływu pracy.Function GetIds() As IList(Of Guid) Dim Ids As New List(Of Guid) Dim localCmd = _ String.Format("Select [InstanceId] from [System.Activities.DurableInstancing].[Instances] Order By [CreationTime]") Using localCon = New SqlConnection(connectionString) Dim cmd As SqlCommand = localCon.CreateCommand() cmd.CommandText = localCmd localCon.Open() Using reader = cmd.ExecuteReader(CommandBehavior.CloseConnection) While reader.Read() 'Get the InstanceId of the persisted Workflow Dim id As Guid = Guid.Parse(reader(0).ToString()) 'Add it to the list. Ids.Add(id) End While End Using End Using Return Ids End Function
static IList<Guid> GetIds() { List<Guid> Ids = new List<Guid>(); string localCmd = string.Format("Select [InstanceId] from [System.Activities.DurableInstancing].[Instances] Order By [CreationTime]"); using (SqlConnection localCon = new SqlConnection(connectionString)) { SqlCommand cmd = localCon.CreateCommand(); cmd.CommandText = localCmd; localCon.Open(); using (SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection)) { while (reader.Read()) { // Get the InstanceId of the persisted Workflow Guid id = Guid.Parse(reader[0].ToString()); // Add it to the list. Ids.Add(id); } } } return Ids; }
Dodaj następującą
LoadMap
metodę doProgram
klasy (lubModule1
). Ta metoda tworzy słownik, który mapujev1
tożsamości przepływu pracy na mapy aktualizacji i nowe tożsamości przepływu pracy używane do aktualizowania odpowiednich trwałych wystąpień przepływu pracy.Function LoadMap(mapName As String) As DynamicUpdateMap Dim mapPath As String = Path.Combine("..\..\..\PreviousVersions", mapName) Dim map As DynamicUpdateMap Using fs As FileStream = File.Open(mapPath, FileMode.Open) Dim serializer As DataContractSerializer = New DataContractSerializer(GetType(DynamicUpdateMap)) Dim updateMap = serializer.ReadObject(fs) If updateMap Is Nothing Then Throw New ApplicationException("DynamicUpdateMap is null.") End If map = updateMap End Using Return map End Function
static DynamicUpdateMap LoadMap(string mapName) { string path = Path.Combine(@"..\..\..\PreviousVersions", mapName); DynamicUpdateMap map; using (FileStream fs = File.Open(path, FileMode.Open)) { DataContractSerializer serializer = new DataContractSerializer(typeof(DynamicUpdateMap)); object updateMap = serializer.ReadObject(fs); if (updateMap == null) { throw new ApplicationException("DynamicUpdateMap is null."); } map = updateMap as DynamicUpdateMap; } return map; }
Dodaj następującą
LoadMaps
metodę doProgram
klasy (lubModule1
). Ta metoda ładuje trzy mapy aktualizacji i tworzy słownik, który mapujev1
tożsamości przepływu pracy na mapy aktualizacji.Function LoadMaps() As IDictionary(Of WorkflowIdentity, DynamicUpdateInfo) 'There are 3 update maps to describe the changes to update v1 workflows, 'one for reach of the 3 workflow types in the tutorial. Dim maps = New Dictionary(Of WorkflowIdentity, DynamicUpdateInfo)() Dim sequentialMap As DynamicUpdateMap = LoadMap("SequentialNumberGuessWorkflow.map") Dim sequentialInfo = New DynamicUpdateInfo With { .updateMap = sequentialMap, .newIdentity = WorkflowVersionMap.SequentialNumberGuessIdentity_v15 } maps.Add(WorkflowVersionMap.SequentialNumberGuessIdentity_v1, sequentialInfo) Dim stateMap As DynamicUpdateMap = LoadMap("StateMachineNumberGuessWorkflow.map") Dim stateInfo = New DynamicUpdateInfo With { .updateMap = stateMap, .newIdentity = WorkflowVersionMap.StateMachineNumberGuessIdentity_v15 } maps.Add(WorkflowVersionMap.StateMachineNumberGuessIdentity_v1, stateInfo) Dim flowchartMap As DynamicUpdateMap = LoadMap("FlowchartNumberGuessWorkflow.map") Dim flowchartInfo = New DynamicUpdateInfo With { .updateMap = flowchartMap, .newIdentity = WorkflowVersionMap.FlowchartNumberGuessIdentity_v15 } maps.Add(WorkflowVersionMap.FlowchartNumberGuessIdentity_v1, flowchartInfo) Return maps End Function
static IDictionary<WorkflowIdentity, DynamicUpdateInfo> LoadMaps() { // There are 3 update maps to describe the changes to update v1 workflows, // one for reach of the 3 workflow types in the tutorial. Dictionary<WorkflowIdentity, DynamicUpdateInfo> maps = new Dictionary<WorkflowIdentity, DynamicUpdateInfo>(); DynamicUpdateMap sequentialMap = LoadMap("SequentialNumberGuessWorkflow.map"); DynamicUpdateInfo sequentialInfo = new DynamicUpdateInfo { updateMap = sequentialMap, newIdentity = WorkflowVersionMap.SequentialNumberGuessIdentity_v15 }; maps.Add(WorkflowVersionMap.SequentialNumberGuessIdentity_v1, sequentialInfo); DynamicUpdateMap stateMap = LoadMap("StateMachineNumberGuessWorkflow.map"); DynamicUpdateInfo stateInfo = new DynamicUpdateInfo { updateMap = stateMap, newIdentity = WorkflowVersionMap.StateMachineNumberGuessIdentity_v15 }; maps.Add(WorkflowVersionMap.StateMachineNumberGuessIdentity_v1, stateInfo); DynamicUpdateMap flowchartMap = LoadMap("FlowchartNumberGuessWorkflow.map"); DynamicUpdateInfo flowchartInfo = new DynamicUpdateInfo { updateMap = flowchartMap, newIdentity = WorkflowVersionMap.FlowchartNumberGuessIdentity_v15 }; maps.Add(WorkflowVersionMap.FlowchartNumberGuessIdentity_v1, flowchartInfo); return maps; }
Dodaj następujący kod do pliku
Main
. Ten kod iteruje utrwalone wystąpienia przepływu pracy i sprawdza każdyWorkflowIdentity
element . Jeśli mapujeWorkflowIdentity
się nav1
wystąpienie przepływu pracy,WorkflowApplication
element jest skonfigurowany ze zaktualizowaną definicją przepływu pracy i zaktualizowaną tożsamością przepływu pracy.WorkflowApplication.Load
Następnie jest wywoływana z wystąpieniem i mapą aktualizacji, która stosuje mapę aktualizacji dynamicznej. Po zastosowaniu aktualizacji zaktualizowane wystąpienie jest utrwalane za pomocą wywołania metodyUnload
.Dim store = New SqlWorkflowInstanceStore(connectionString) WorkflowApplication.CreateDefaultInstanceOwner(store, Nothing, WorkflowIdentityFilter.Any) Dim updateMaps As IDictionary(Of WorkflowIdentity, DynamicUpdateInfo) = LoadMaps() For Each id As Guid In GetIds() 'Get a proxy to the instance. Dim instance As WorkflowApplicationInstance = WorkflowApplication.GetInstance(id, store) Console.WriteLine("Inspecting: {0}", instance.DefinitionIdentity) 'Only update v1 workflows. If Not instance.DefinitionIdentity Is Nothing AndAlso _ instance.DefinitionIdentity.Version.Equals(New Version(1, 0, 0, 0)) Then Dim info As DynamicUpdateInfo = updateMaps(instance.DefinitionIdentity) 'Associate the persisted WorkflowApplicationInstance with 'a WorkflowApplication that is configured with the updated 'definition and updated WorkflowIdentity. Dim wf As Activity = WorkflowVersionMap.GetWorkflowDefinition(info.newIdentity) Dim wfApp = New WorkflowApplication(wf, info.newIdentity) 'Apply the Dynamic Update. wfApp.Load(instance, info.updateMap) 'Persist the updated instance. wfApp.Unload() Console.WriteLine("Updated to: {0}", info.newIdentity) Else 'Not updating this instance, so unload it. instance.Abandon() End If Next
SqlWorkflowInstanceStore store = new SqlWorkflowInstanceStore(connectionString); WorkflowApplication.CreateDefaultInstanceOwner(store, null, WorkflowIdentityFilter.Any); IDictionary<WorkflowIdentity, DynamicUpdateInfo> updateMaps = LoadMaps(); foreach (Guid id in GetIds()) { // Get a proxy to the instance. WorkflowApplicationInstance instance = WorkflowApplication.GetInstance(id, store); Console.WriteLine("Inspecting: {0}", instance.DefinitionIdentity); // Only update v1 workflows. if (instance.DefinitionIdentity != null && instance.DefinitionIdentity.Version.Equals(new Version(1, 0, 0, 0))) { DynamicUpdateInfo info = updateMaps[instance.DefinitionIdentity]; // Associate the persisted WorkflowApplicationInstance with // a WorkflowApplication that is configured with the updated // definition and updated WorkflowIdentity. Activity wf = WorkflowVersionMap.GetWorkflowDefinition(info.newIdentity); WorkflowApplication wfApp = new WorkflowApplication(wf, info.newIdentity); // Apply the Dynamic Update. wfApp.Load(instance, info.updateMap); // Persist the updated instance. wfApp.Unload(); Console.WriteLine("Updated to: {0}", info.newIdentity); } else { // Not updating this instance, so unload it. instance.Abandon(); } }
Kliknij prawym przyciskiem myszy pozycję ApplyDynamicUpdate w Eksplorator rozwiązań i wybierz polecenie Ustaw jako projekt startowy.
Naciśnij Ctrl+Shift+B, aby skompilować rozwiązanie, a następnie naciśnij Ctrl+F5, aby uruchomić aplikację
ApplyDynamicUpdate
i zaktualizować utrwalone wystąpienia przepływu pracy. Wyświetlone dane wyjściowe powinny wyglądać mniej więcej tak. Przepływy pracy w wersji 1.0.0.0 są aktualizowane do wersji 1.5.0.0, podczas gdy przepływy pracy w wersji 2.0.0.0 nie są aktualizowane.Inspekcja: StateMachineNumberGuessWorkflow; Wersja=1.0.0.0
Zaktualizowano do: StateMachineNumberGuessWorkflow; Wersja=1.5.0.0
Inspekcja: StateMachineNumberGuessWorkflow; Wersja=1.0.0.0
Zaktualizowano do: StateMachineNumberGuessWorkflow; Wersja=1.5.0.0
Inspekcja: Schemat blokowyNumberGuessWorkflow; Wersja=1.0.0.0
Zaktualizowano do: Schemat blokowyNumberGuessWorkflow; Wersja=1.5.0.0
Inspekcja: Schemat blokowyNumberGuessWorkflow; Wersja=1.0.0.0
Zaktualizowano do: Schemat blokowyNumberGuessWorkflow; Wersja=1.5.0.0
Inspekcja: SekwencyjneNumberGuessWorkflow; Wersja=1.0.0.0
Zaktualizowano do: SekwencyjneNumberGuessWorkflow; Wersja=1.5.0.0
Inspekcja: SekwencyjneNumberGuessWorkflow; Wersja=1.0.0.0
Zaktualizowano do: SekwencyjneNumberGuessWorkflow; Wersja=1.5.0.0
Inspekcja: SekwencyjneNumberGuessWorkflow; Wersja=1.0.0.0
Zaktualizowano do: SekwencyjneNumberGuessWorkflow; Wersja=1.5.0.0
Inspekcja: StateMachineNumberGuessWorkflow; Wersja=1.0.0.0
Zaktualizowano do: StateMachineNumberGuessWorkflow; Wersja=1.5.0.0
Inspekcja: Schemat blokowyNumberGuessWorkflow; Wersja=1.0.0.0
Zaktualizowano do: Schemat blokowyNumberGuessWorkflow; Wersja=1.5.0.0
Inspekcja: StateMachineNumberGuessWorkflow; Wersja=2.0.0.0
Inspekcja: StateMachineNumberGuessWorkflow; Wersja=2.0.0.0
Inspekcja: Schemat blokowyNumberGuessWorkflow; Wersja=2.0.0.0
Inspekcja: Schemat blokowyNumberGuessWorkflow; Wersja=2.0.0.0
Inspekcja: SekwencyjneNumberGuessWorkflow; Wersja=2.0.0.0
Inspekcja: SekwencyjneNumberGuessWorkflow; Wersja=2.0.0.0
Naciśnij dowolny, aby kontynuować . . .
Aby uruchomić aplikację ze zaktualizowanymi przepływami pracy
Kliknij prawym przyciskiem myszy pozycję NumberGuessWorkflowHost w Eksplorator rozwiązań i wybierz polecenie Ustaw jako projekt startowy.
Naciśnij klawisze CTRL+F5, aby uruchomić aplikację.
Kliknij pozycję Nowa gra , aby rozpocząć nowy przepływ pracy i zanotuj informacje o wersji poniżej okna stanu, które wskazuje, że przepływ pracy jest przepływem
v2
pracy.Wybierz jeden z
v1
przepływów pracy uruchomionych na początku tematu Instrukcje: hostowanie wielu wersji przepływu pracy obok siebie . Należy pamiętać, że informacje o wersji w oknie stanu wskazują, że przepływ pracy jest przepływem pracy w wersji 1.5.0.0 . Należy pamiętać, że nie ma żadnych informacji na temat poprzednich zgadywania innych niż to, czy były zbyt wysokie, czy zbyt niskie.Wprowadź liczbę z zakresu od 1 do 10
Twoje zgadywanie jest zbyt niskie.Zanotuj wartości ,
InstanceId
a następnie wprowadź odgadnięcia do momentu zakończenia przepływu pracy. W oknie stanu są wyświetlane informacje o zawartości odgadnięcia, ponieważWriteLine
działania zostały zaktualizowane przez aktualizację dynamiczną.Wprowadź liczbę z zakresu od 1 do 10
Twoje zgadywanie jest zbyt niskie.
Wprowadź liczbę z zakresu od 1 do 10
5 jest zbyt niskie.
Wprowadź liczbę z zakresu od 1 do 10
7 jest zbyt wysokie.
Wprowadź liczbę z zakresu od 1 do 10
Gratulacje, odgadłeś liczbę w 4 zakrętach.Otwórz Eksploratora Windows i przejdź do folderu NumberGuessWorkflowHost\bin\debug (lub bin\release w zależności od ustawień projektu) i otwórz plik śledzenia przy użyciu Notatnika odpowiadającego ukończonego przepływu pracy. Jeśli nie zanotujesz pliku
InstanceId
śledzenia, możesz zidentyfikować prawidłowy plik śledzenia przy użyciu informacji zmodyfikowanych daty w Eksploratorze Windows. Ostatni wiersz informacji o śledzeniu zawiera dane wyjściowe nowo dodanegoWriteLine
działania.Wprowadź liczbę z zakresu od 1 do 10
Twoje zgadywanie jest zbyt niskie.
Wprowadź liczbę z zakresu od 1 do 10
5 jest zbyt niskie.
Wprowadź liczbę z zakresu od 1 do 10
7 jest zbyt wysokie.
Wprowadź liczbę z zakresu od 1 do 10
6 jest poprawne. Domyśliłeś się, że to na 4 zakręty.
Aby włączyć uruchamianie poprzednich wersji przepływów pracy
Jeśli zabraknie przepływów pracy do zaktualizowania, możesz zmodyfikować aplikację NumberGuessWorkflowHost
, aby włączyć uruchamianie poprzednich wersji przepływów pracy.
Kliknij dwukrotnie element WorkflowHostForm w Eksplorator rozwiązań i wybierz pole kombi WorkflowType.
W oknie Właściwości wybierz właściwość Items i kliknij przycisk wielokropka, aby edytować kolekcję Items.
Dodaj następujące trzy elementy do kolekcji.
StateMachineNumberGuessWorkflow v1 FlowchartNumberGuessWorkflow v1 SequentialNumberGuessWorkflow v1
Ukończona
Items
kolekcja będzie miała sześć elementów.StateMachineNumberGuessWorkflow FlowchartNumberGuessWorkflow SequentialNumberGuessWorkflow StateMachineNumberGuessWorkflow v1 FlowchartNumberGuessWorkflow v1 SequentialNumberGuessWorkflow v1
Kliknij dwukrotnie element WorkflowHostForm w Eksplorator rozwiązań, a następnie wybierz pozycję Wyświetl kod.
Dodaj trzy nowe przypadki do instrukcji
switch
(lubSelect Case
) w procedurzeNewGame_Click
obsługi, aby zamapować nowe elementy w polu kombi WorkflowType na pasujące tożsamości przepływu pracy.Case "SequentialNumberGuessWorkflow v1" identity = WorkflowVersionMap.SequentialNumberGuessIdentity_v1 Case "StateMachineNumberGuessWorkflow v1" identity = WorkflowVersionMap.StateMachineNumberGuessIdentity_v1 Case "FlowchartNumberGuessWorkflow v1" identity = WorkflowVersionMap.FlowchartNumberGuessIdentity_v1
case "SequentialNumberGuessWorkflow v1": identity = WorkflowVersionMap.SequentialNumberGuessIdentity_v1; break; case "StateMachineNumberGuessWorkflow v1": identity = WorkflowVersionMap.StateMachineNumberGuessIdentity_v1; break; case "FlowchartNumberGuessWorkflow v1": identity = WorkflowVersionMap.FlowchartNumberGuessIdentity_v1; break;
Poniższy przykład zawiera kompletną
switch
instrukcję (lubSelect Case
).Select Case WorkflowType.SelectedItem.ToString() Case "SequentialNumberGuessWorkflow" identity = WorkflowVersionMap.SequentialNumberGuessIdentity Case "StateMachineNumberGuessWorkflow" identity = WorkflowVersionMap.StateMachineNumberGuessIdentity Case "FlowchartNumberGuessWorkflow" identity = WorkflowVersionMap.FlowchartNumberGuessIdentity Case "SequentialNumberGuessWorkflow v1" identity = WorkflowVersionMap.SequentialNumberGuessIdentity_v1 Case "StateMachineNumberGuessWorkflow v1" identity = WorkflowVersionMap.StateMachineNumberGuessIdentity_v1 Case "FlowchartNumberGuessWorkflow v1" identity = WorkflowVersionMap.FlowchartNumberGuessIdentity_v1 End Select
switch (WorkflowType.SelectedItem.ToString()) { case "SequentialNumberGuessWorkflow": identity = WorkflowVersionMap.SequentialNumberGuessIdentity; break; case "StateMachineNumberGuessWorkflow": identity = WorkflowVersionMap.StateMachineNumberGuessIdentity; break; case "FlowchartNumberGuessWorkflow": identity = WorkflowVersionMap.FlowchartNumberGuessIdentity; break; case "SequentialNumberGuessWorkflow v1": identity = WorkflowVersionMap.SequentialNumberGuessIdentity_v1; break; case "StateMachineNumberGuessWorkflow v1": identity = WorkflowVersionMap.StateMachineNumberGuessIdentity_v1; break; case "FlowchartNumberGuessWorkflow v1": identity = WorkflowVersionMap.FlowchartNumberGuessIdentity_v1; break; };
Naciśnij CTRL+F5, aby skompilować i uruchomić aplikację. Teraz możesz uruchomić
v1
wersje przepływu pracy, a także bieżące wersje. Aby dynamicznie aktualizować te nowe wystąpienia, uruchom aplikację ApplyDynamicUpdate .