Anvisningar: Uppdatera definitionen av en arbetsflödesinstans som körs
Dynamisk uppdatering ger en mekanism för utvecklare av arbetsflödesprogram för att uppdatera arbetsflödesdefinitionen för en instans av ett sparat arbetsflöde. Den nödvändiga ändringen kan vara att implementera en felkorrigering, nya krav eller för att hantera oväntade ändringar. Det här steget i självstudien visar hur du använder dynamisk uppdatering för att ändra bevarade instanser av v1
arbetsflödet för antal gissningar för att matcha de nya funktionerna som introduceras i Så här: Värd flera versioner av ett arbetsflöde sida vid sida.
Skapa CreateUpdateMaps-projektet
Högerklicka på WF45GettingStartedTutorial i Solution Explorer och välj Lägg till, Nytt projekt.
I noden Installerad väljer du Visual C#, Windows (eller Visual Basic, Windows).
Kommentar
Beroende på vilket programmeringsspråk som konfigureras som primärt språk i Visual Studio kan noden Visual C# eller Visual Basic finnas under noden Andra språk i noden Installerad .
Kontrollera att .NET Framework 4.5 är markerat i listrutan .NET Framework-version. Välj Konsolprogram i Windows-listan. Skriv CreateUpdateMaps i rutan Namn och klicka på OK.
Högerklicka på CreateUpdateMaps i Solution Explorer och välj Lägg till referens.
Välj Framework från noden Sammansättningar i listan Lägg till referens . Skriv System.Activities i rutan Söksammansättningar för att filtrera sammansättningarna och göra önskade referenser enklare att välja.
Markera kryssrutan bredvid System.Activities i listan Sökresultat .
Skriv Serialisering i rutan Söksammansättningar och markera kryssrutan bredvid System.Runtime.Serialization i listan Sökresultat .
Skriv System.Xaml i rutan Söksammansättningar och markera kryssrutan bredvid System.Xaml i listan Sökresultat .
Klicka på OK för att stänga Referenshanteraren och lägga till referenserna.
Lägg till följande
using
(ellerImports
) -instruktioner överst i filen med de andrausing
(ellerImports
) -uttrycken.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;
Lägg till följande två strängmedlemmar i
Program
klassen (ellerModule1
).Const mapPath = "..\..\..\PreviousVersions" Const definitionPath = "..\..\..\NumberGuessWorkflowActivities_du"
const string mapPath = @"..\..\..\PreviousVersions"; const string definitionPath = @"..\..\..\NumberGuessWorkflowActivities_du";
Lägg till följande
StartUpdate
metod iProgram
klassen (ellerModule1
). Den här metoden läser in den angivna xaml-arbetsflödesdefinitionen i enActivityBuilder
, och anroparDynamicUpdate.PrepareForUpdate
sedan .PrepareForUpdate
gör en kopia av arbetsflödesdefinitionenActivityBuilder
i . När arbetsflödesdefinitionen har ändrats används den här kopian tillsammans med den ändrade arbetsflödesdefinitionen för att skapa uppdateringskartan.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; }
Lägg sedan till följande
CreateUpdateMethod
iProgram
klassen (ellerModule1
). Detta skapar en dynamisk uppdateringskarta genom att anropa DynamicUpdateServices.CreateUpdateMap och sparar sedan uppdateringskartan med det angivna namnet. Den här uppdateringskartan innehåller den information som krävs av arbetsflödeskörningen för att uppdatera en instans av ett beständiga arbetsflöde som startades med den ursprungliga arbetsflödesdefinitionenActivityBuilder
som finns i så att den slutförs med hjälp av den uppdaterade arbetsflödesdefinitionen.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); } }
Lägg till följande
SaveUpdatedDefinition
metod iProgram
klassen (ellerModule1
). Den här metoden sparar den uppdaterade arbetsflödesdefinitionen när uppdateringskartan har skapats.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(); }
Uppdatera StateMachineNumberGuessWorkflow
Lägg till en
CreateStateMachineUpdateMap
iProgram
klassen (ellerModule1
).Private Sub CreateStateMachineUpdateMap() End Sub
private static void CreateStateMachineUpdateMap() { }
StartUpdate
Anropa och hämta sedan en referens till arbetsflödets rotaktivitetStateMachine
.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;
Uppdatera sedan uttrycken för de två
WriteLine
aktiviteter som visar om användarens gissning är för hög eller för låg så att de matchar de uppdateringar som görs i Så här: Värd för flera versioner av ett arbetsflöde sida vid sida.'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.\"");
Lägg sedan till den nya
WriteLine
aktiviteten som visar det avslutande meddelandet.'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;
När arbetsflödet har uppdaterats anropar
CreateUpdateMaps
du ochSaveUpdatedDefinition
.CreateUpdateMaps
skapar och spararDynamicUpdateMap
, ochSaveUpdatedDefinition
sparar den uppdaterade arbetsflödesdefinitionen.'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");
Följande exempel är den slutförda
CreateStateMachineUpdateMap
metoden.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"); }
Uppdatera FlowchartNumberGuessWorkflow
Lägg till följande
CreateFlowchartUpdateMethod
iProgram
klassen (ellerModule1
). Den här metoden liknarCreateStateMachineUpdateMap
. Det börjar med ett anrop tillStartUpdate
, uppdaterar arbetsflödesdefinitionen för flödesschemat och avslutas genom att spara uppdateringskartan och den uppdaterade arbetsflödesdefinitionen.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"); }
Uppdatera SekventielltNumberGuessWorkflow
Lägg till följande
CreateSequentialUpdateMethod
iProgram
klassen (ellerModule1
). Den här metoden liknar de andra två metoderna. Det börjar med ett anrop tillStartUpdate
, uppdaterar definitionen för sekventiellt arbetsflöde och avslutas genom att spara uppdateringskartan och den uppdaterade arbetsflödesdefinitionen.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"); }
Skapa och köra CreateUpdateMaps-programmet
Main
Uppdatera metoden och lägg till följande tre metodanrop. Dessa metoder läggs till i följande avsnitt. Varje metod uppdaterar motsvarande arbetsflöde för antal gissningar och skapar ettDynamicUpdateMap
som beskriver uppdateringarna.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(); }
Högerklicka på CreateUpdateMaps i Solution Explorer och välj Ange som startprojekt.
Tryck på CTRL+SKIFT+B för att skapa lösningen och sedan CTRL+F5 för att köra
CreateUpdateMaps
programmet.Kommentar
Programmet
CreateUpdateMaps
visar ingen statusinformation när det körs, men om du tittar i mappen NumberGuessWorkflowActivities_du och mappen PreviousVersions visas de uppdaterade arbetsflödesdefinitionsfilerna och uppdateringskartorna.När uppdateringskartorna har skapats och arbetsflödesdefinitionerna har uppdaterats är nästa steg att skapa en uppdaterad arbetsflödessammansättning som innehåller de uppdaterade definitionerna.
Skapa den uppdaterade arbetsflödessammansättningen
Öppna en andra instans av Visual Studio 2012.
Välj Öppna, Projekt/Lösning på Arkiv-menyn .
Gå till den NumberGuessWorkflowActivities_du mapp som du skapade i Så här: Värd för flera versioner av ett arbetsflöde sida vid sida, välj NumberGuessWorkflowActivities.csproj (eller vbproj) och klicka på Öppna.
Högerklicka på SekventielltNumberGuessWorkflow.xaml i Solution Explorer och välj Exkludera från projekt. Gör samma sak för FlowchartNumberGuessWorkflow.xaml och StateMachineNumberGuessWorkflow.xaml. Det här steget tar bort de tidigare versionerna av arbetsflödesdefinitionerna från projektet.
Välj Lägg till befintligt objekt på projektmenyn .
Gå till den NumberGuessWorkflowActivities_du mapp som du skapade i Så här: Värd för flera versioner av ett arbetsflöde sida vid sida.
Välj XAML-filer (*.xaml;*.xoml) i listrutan Filer av typen .
Välj SequentialNumberGuessWorkflow_du.xaml, FlowchartNumberGuessWorkflow_du.xaml och StateMachineNumberGuessWorkflow_du.xaml och klicka på Lägg till.
Kommentar
CTRL+Klicka om du vill markera flera objekt i taget.
Det här steget lägger till de uppdaterade versionerna av arbetsflödesdefinitionerna i projektet.
Tryck på CTRL+SKIFT+B för att skapa projektet.
Välj Stäng lösning på Arkiv-menyn . En lösningsfil för projektet krävs inte, så klicka på Nej för att stänga Visual Studio utan att spara en lösningsfil. Välj Avsluta på Arkiv-menyn för att stänga Visual Studio.
Öppna Utforskaren och gå till mappen NumberGuessWorkflowActivities_du\bin\Debug (eller bin\Release beroende på projektinställningarna).
Byt namn på NumberGuessWorkflowActivities.dll till NumberGuessWorkflowActivities_v15.dll och kopiera den till mappen PreviousVersions som du skapade i Så här: Värd för flera versioner av ett arbetsflöde sida vid sida.
Uppdatera WorkflowVersionMap med de nya versionerna
Växla tillbaka till den första instansen av Visual Studio 2012.
Dubbelklicka på WorkflowVersionMap.cs (eller WorkflowVersionMap.vb) under projektet NumberGuessWorkflowHost för att öppna det.
Lägg till tre nya arbetsflödesidentiteter strax under de sex befintliga arbetsflödesidentitetsdeklarationerna. I den här självstudien
1.5.0.0
WorkflowIdentity.Version
används som för dynamiska uppdateringsidentiteter. Dessa nyav15
arbetsflödesidentiteter används för att ge rätt arbetsflödesdefinition för dynamiskt uppdaterade instanser av bevarade arbetsflöden.'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;
Lägg till följande kod i slutet av konstruktorn. Den här koden initierar identiteterna för dynamiskt uppdateringsarbetsflöde, läser in motsvarande arbetsflödesdefinitioner och lägger till dem i ordlistan för arbetsflödesversion.
'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);
Följande exempel är den slutförda
WorkflowVersionMap
klassen.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(); } }
Tryck på CTRL+SKIFT+B för att skapa projektet.
Så här tillämpar du de dynamiska uppdateringarna
Högerklicka på WF45GettingStartedTutorial i Solution Explorer och välj Lägg till, Nytt projekt.
I noden Installerad väljer du Visual C#, Windows (eller Visual Basic, Windows).
Kommentar
Beroende på vilket programmeringsspråk som konfigureras som primärt språk i Visual Studio kan noden Visual C# eller Visual Basic finnas under noden Andra språk i noden Installerad .
Kontrollera att .NET Framework 4.5 är markerat i listrutan .NET Framework-version. Välj Konsolprogram i Windows-listan. Skriv ApplyDynamicUpdate i rutan Namn och klicka på OK.
Högerklicka på ApplyDynamicUpdate i Solution Explorer och välj Lägg till referens.
Klicka på Lösning och markera kryssrutan bredvid NumberGuessWorkflowHost. Den här referensen
NumberGuessWorkflowHost.WorkflowVersionMap
behövs så attApplyDynamicUpdate
du kan använda klassen.Välj Framework från noden Sammansättningar i listan Lägg till referens . Skriv System.Activities i rutan Söksammansättningar . Detta filtrerar sammansättningarna och gör önskade referenser enklare att välja.
Markera kryssrutan bredvid System.Activities i listan Sökresultat .
Skriv Serialisering i rutan Söksammansättningar och markera kryssrutan bredvid System.Runtime.Serialization i listan Sökresultat .
Skriv DurableInstancing i rutan Söksammansättningar och markera kryssrutan bredvid System.Activities.DurableInstancing och System.Runtime.DurableInstancing från listan Sökresultat .
Klicka på OK för att stänga Referenshanteraren och lägga till referenserna.
Högerklicka på ApplyDynamicUpdate i Solution Explorer och välj Lägg till, klass. Skriv
DynamicUpdateInfo
i rutan Namn och klicka på Lägg till.Lägg till följande två medlemmar i
DynamicUpdateInfo
klassen. Följande exempel är den slutfördaDynamicUpdateInfo
klassen. Den här klassen innehåller information om uppdateringskartan och den nya arbetsflödesidentiteten som används när en arbetsflödesinstans uppdateras.Public Class DynamicUpdateInfo Public updateMap As DynamicUpdateMap Public newIdentity As WorkflowIdentity End Class
class DynamicUpdateInfo { public DynamicUpdateMap updateMap; public WorkflowIdentity newIdentity; }
Lägg till följande
using
(ellerImports
) -instruktioner överst i filen med de andrausing
(ellerImports
) -uttrycken.Imports System.Activities Imports System.Activities.DynamicUpdate
using System.Activities; using System.Activities.DynamicUpdate;
Dubbelklicka på Program.cs (eller Module1.vb) i Solution Explorer.
Lägg till följande
using
(ellerImports
) -instruktioner överst i filen med de andrausing
(ellerImports
) -uttrycken.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;
Lägg till följande anslutningssträng medlem i
Program
klassen (ellerModule1
).Const connectionString = "Server=.\SQLEXPRESS;Initial Catalog=WF45GettingStartedTutorial;Integrated Security=SSPI"
const string connectionString = "Server=.\\SQLEXPRESS;Initial Catalog=WF45GettingStartedTutorial;Integrated Security=SSPI";
Viktigt!
Microsoft rekommenderar att du använder det säkraste tillgängliga autentiseringsflödet. Om du ansluter till Azure SQL är hanterade identiteter för Azure-resurser den rekommenderade autentiseringsmetoden.
Kommentar
Beroende på din utgåva av SQL Server kan anslutningssträng servernamnet vara annorlunda.
Lägg till följande
GetIDs
metod iProgram
klassen (ellerModule1
). Den här metoden returnerar en lista över bevarade arbetsflödesinstans-ID:er.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; }
Lägg till följande
LoadMap
metod iProgram
klassen (ellerModule1
). Den här metoden skapar en ordlista som mapparv1
arbetsflödesidentiteter till uppdateringskartor och nya arbetsflödesidentiteter som används för att uppdatera motsvarande bevarade arbetsflödesinstanser.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; }
Lägg till följande
LoadMaps
metod iProgram
klassen (ellerModule1
). Den här metoden läser in de tre uppdateringskartningarna och skapar en ordlista som mapparv1
arbetsflödesidentiteter till uppdateringskartningarna.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; }
Lägg till följande kod i
Main
. Den här koden itererar de bevarade arbetsflödesinstanserna och undersöker varjeWorkflowIdentity
. Om mappar tillWorkflowIdentity
env1
arbetsflödesinstans konfigureras enWorkflowApplication
med den uppdaterade arbetsflödesdefinitionen och en uppdaterad arbetsflödesidentitet.WorkflowApplication.Load
Därefter anropas med instansen och uppdateringskartan, som tillämpar den dynamiska uppdateringskartan. När uppdateringen har tillämpats sparas den uppdaterade instansen med ett anrop tillUnload
.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(); } }
Högerklicka på ApplyDynamicUpdate i Solution Explorer och välj Ange som startprojekt.
Tryck på Ctrl+Skift+B för att skapa lösningen och tryck sedan på Ctrl+F5 för att köra
ApplyDynamicUpdate
programmet och uppdatera de bevarade arbetsflödesinstanserna. Du bör se utdata som liknar följande. Arbetsflödena i version 1.0.0.0 uppdateras till version 1.5.0.0, medan arbetsflödena i version 2.0.0.0 inte uppdateras.Inspektera: StateMachineNumberGuessWorkflow; Version=1.0.0.0
Uppdaterad till: StateMachineNumberGuessWorkflow; Version=1.5.0.0
Inspektera: StateMachineNumberGuessWorkflow; Version=1.0.0.0
Uppdaterad till: StateMachineNumberGuessWorkflow; Version=1.5.0.0
Inspektera: FlowchartNumberGuessWorkflow; Version=1.0.0.0
Uppdaterad till: FlowchartNumberGuessWorkflow; Version=1.5.0.0
Inspektera: FlowchartNumberGuessWorkflow; Version=1.0.0.0
Uppdaterad till: FlowchartNumberGuessWorkflow; Version=1.5.0.0
Inspektera: SekventielltNumberGuessWorkflow; Version=1.0.0.0
Uppdaterad till: SekventielltNumberGuessWorkflow; Version=1.5.0.0
Inspektera: SekventielltNumberGuessWorkflow; Version=1.0.0.0
Uppdaterad till: SekventielltNumberGuessWorkflow; Version=1.5.0.0
Inspektera: SekventielltNumberGuessWorkflow; Version=1.0.0.0
Uppdaterad till: SekventielltNumberGuessWorkflow; Version=1.5.0.0
Inspektera: StateMachineNumberGuessWorkflow; Version=1.0.0.0
Uppdaterad till: StateMachineNumberGuessWorkflow; Version=1.5.0.0
Inspektera: FlowchartNumberGuessWorkflow; Version=1.0.0.0
Uppdaterad till: FlowchartNumberGuessWorkflow; Version=1.5.0.0
Inspektera: StateMachineNumberGuessWorkflow; Version=2.0.0.0
Inspektera: StateMachineNumberGuessWorkflow; Version=2.0.0.0
Inspektera: FlowchartNumberGuessWorkflow; Version=2.0.0.0
Inspektera: FlowchartNumberGuessWorkflow; Version=2.0.0.0
Inspektera: SekventielltNumberGuessWorkflow; Version=2.0.0.0
Inspektera: SekventielltNumberGuessWorkflow; Version=2.0.0.0
Tryck på valfri tangent för att fortsätta . . .
Så här kör du programmet med de uppdaterade arbetsflödena
Högerklicka på NumberGuessWorkflowHost i Solution Explorer och välj Ange som startprojekt.
Tryck på CTRL+F5 för att köra programmet.
Klicka på Nytt spel för att starta ett nytt arbetsflöde och notera versionsinformationen under statusfönstret som anger att arbetsflödet är ett
v2
arbetsflöde.Välj ett av de arbetsflöden
v1
som du startade i början av avsnittet Så här: Värd för flera versioner av ett arbetsflöde sida vid sida . Observera att versionsinformationen under statusfönstret anger att arbetsflödet är ett arbetsflöde i version 1.5.0.0 . Observera att det inte finns någon annan information om tidigare gissningar än om de var för höga eller för låga.Ange ett tal mellan 1 och 10
Din gissning är för låg.Anteckna
InstanceId
och ange sedan gissningar tills arbetsflödet har slutförts. Statusfönstret visar information om innehållet i gissningen eftersom aktiviteternaWriteLine
uppdaterades av den dynamiska uppdateringen.Ange ett tal mellan 1 och 10
Din gissning är för låg.
Ange ett tal mellan 1 och 10
5 är för låg.
Ange ett tal mellan 1 och 10
7 är för hög.
Ange ett tal mellan 1 och 10
Grattis, du gissade numret i 4 varv.Öppna Utforskaren och gå till mappen NumberGuessWorkflowHost\bin\debug (eller bin\release beroende på projektinställningarna) och öppna spårningsfilen med Anteckningar som motsvarar det slutförda arbetsflödet. Om du inte antecknar kanske du kan identifiera rätt spårningsfil med hjälp av den datummodifierade informationen i Utforskaren.
InstanceId
Den sista raden i spårningsinformationen innehåller utdata från den nyligen tillagdaWriteLine
aktiviteten.Ange ett tal mellan 1 och 10
Din gissning är för låg.
Ange ett tal mellan 1 och 10
5 är för låg.
Ange ett tal mellan 1 och 10
7 är för hög.
Ange ett tal mellan 1 och 10
6 är korrekt. Du gissade det i 4 varv.
Aktivera start av tidigare versioner av arbetsflöden
Om du får slut på arbetsflöden som ska uppdateras kan du ändra NumberGuessWorkflowHost
programmet så att du kan starta tidigare versioner av arbetsflödena.
Dubbelklicka på WorkflowHostForm i Solution Explorer och välj kombinationsrutan WorkflowType .
I fönstret Egenskaper väljer du egenskapen Objekt och klickar på ellipsknappen för att redigera samlingen Objekt .
Lägg till följande tre objekt i samlingen.
StateMachineNumberGuessWorkflow v1 FlowchartNumberGuessWorkflow v1 SequentialNumberGuessWorkflow v1
Den slutförda
Items
samlingen innehåller sex objekt.StateMachineNumberGuessWorkflow FlowchartNumberGuessWorkflow SequentialNumberGuessWorkflow StateMachineNumberGuessWorkflow v1 FlowchartNumberGuessWorkflow v1 SequentialNumberGuessWorkflow v1
Dubbelklicka på WorkflowHostForm i Solution Explorer och välj Visa kod.
Lägg till tre nya fall i -instruktionen
switch
NewGame_Click
(ellerSelect Case
) i hanteraren för att mappa de nya objekten i kombinationsrutan WorkflowType till matchande arbetsflödesidentiteter.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;
Följande exempel innehåller den fullständiga
switch
(ellerSelect Case
) instruktionen.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; };
Tryck på CTRL+F5 för att skapa och köra programmet. Nu kan du starta versionerna
v1
av arbetsflödet samt de aktuella versionerna. Om du vill uppdatera dessa nya instanser dynamiskt kör du programmet ApplyDynamicUpdate .