Como: atualizar a definição de uma instância de fluxo de trabalho em execução
A atualização dinâmica fornece um mecanismo para que os desenvolvedores de aplicativos de fluxo de trabalho atualizem a definição de fluxo de trabalho de uma instância do fluxo de trabalho persistida. A alteração necessária pode ser implementar uma correção de bug, novos requisitos ou acomodar alterações inesperadas. Esta etapa do tutorial demonstra como usar a atualização dinâmica para modificar instâncias persistentes do fluxo de trabalho de adivinhação de número v1
para corresponder à nova funcionalidade apresentada em Como: hospedar várias versões de um fluxo de trabalho lado a lado.
Para criar o projeto CreateUpdateMaps
Clique com o botão direito do mouse em WF45GettingStartedTutorial no Gerenciador de Soluções e escolha Adicionar, Novo projeto.
No nó Instalado, selecione Visual C#, Windows (ou Visual Basic, Windows).
Observação
Dependendo da linguagem de programação que esteja configurada como linguagem primária no Visual Studio, o nó Visual C# ou Visual Basic poderá estar sob o nó Outras Linguagens no nó Instalado.
Certifique-se de que o .NET Framework 4.5 esteja selecionado na lista suspensa de versões do .NET Framework. Selecione Aplicativo de console na lista Windows. Digite CreateUpdateMaps na caixa Nome e clique em OK.
Clique com o botão direito do mouse em CreateUpdateMaps no Gerenciador de Soluções e escolha Add Reference.
Selecione Framework no nó Assemblies na lista Add Reference. Digite System.Activities na caixa Pesquisar assemblies para filtrar os assemblies e facilitar a seleção das referências desejadas.
Marque a caixa de seleção ao lado de System.Activities na lista Resultados da pesquisa.
Digite Serialization na caixa Search Assemblies e marque a caixa de seleção ao lado de System.Runtime.Serialization na lista Search Results.
Digite System.Xaml na caixa Pesquisar assemblies e marque a caixa de seleção ao lado de System.Xaml na lista Resultados da pesquisa.
Clique em OK para fechar o Gerenciador de referências e adicionar as referências.
Adicione as seguintes instruções
using
(ouImports
) na parte superior do arquivo com as outras instruçõesusing
(ouImports
).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;
Adicionar os dois membros de cadeia de caracteres a seguir à classe
Program
(ouModule1
).Const mapPath = "..\..\..\PreviousVersions" Const definitionPath = "..\..\..\NumberGuessWorkflowActivities_du"
const string mapPath = @"..\..\..\PreviousVersions"; const string definitionPath = @"..\..\..\NumberGuessWorkflowActivities_du";
Adicione o método
StartUpdate
a seguir à classeProgram
(ouModule1
). Esse método carrega acima uma definição do fluxo de trabalho do xaml especificado em umActivityBuilder
e chamaDynamicUpdate.PrepareForUpdate
. OPrepareForUpdate
faz uma cópia da definição de fluxo de trabalho dentro doActivityBuilder
. Depois que a definição de fluxo de trabalho tiver sido alterada, essa cópia será usada junto com a definição de fluxo de trabalho alterada para criar o mapa de atualização.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; }
Em seguida, adicione o
CreateUpdateMethod
a seguir à classeProgram
(ouModule1
). Isso cria um mapa dinâmico de atualização chamando DynamicUpdateServices.CreateUpdateMap e, em seguida, salva o mapa de atualização usando o nome especificado. Esse mapa de atualização contém as informações necessárias pelo runtime de fluxo de trabalho para atualizar uma instância do fluxo de trabalho persistida, que foi iniciada usando a definição original de fluxo de trabalho contida noActivityBuilder
, de forma que ela fosse concluída usando a definição atualizada do fluxo de trabalho.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); } }
Adicione o método
SaveUpdatedDefinition
a seguir à classeProgram
(ouModule1
). Esse método salva a definição atualizada de fluxo de trabalho quando o mapa de atualização é criado.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(); }
Para atualizar StateMachineNumberGuessWorkflow
Adicione um
CreateStateMachineUpdateMap
à classeProgram
(ouModule1
).Private Sub CreateStateMachineUpdateMap() End Sub
private static void CreateStateMachineUpdateMap() { }
Faz uma chamada para
StartUpdate
e obtém uma referência à atividade raizStateMachine
do fluxo de trabalho.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;
Em seguida, atualize as expressões das duas atividades
WriteLine
que exibem se a estimativa do usuário é muito alta ou muito baixa para que correspondam às atualizações feitas em Como: Hospedar várias versões de um fluxo de trabalho lado a lado.'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.\"");
Em seguida, adicione a nova atividade
WriteLine
que exibe a mensagem de fechamento.'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;
Depois que o fluxo de trabalho é atualizado, chame
CreateUpdateMaps
eSaveUpdatedDefinition
.CreateUpdateMaps
cria e salva oDynamicUpdateMap
e oSaveUpdatedDefinition
salva a definição atualizada do fluxo de trabalho.'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");
O exemplo a seguir é o método
CreateStateMachineUpdateMap
concluído.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"); }
Para atualizar FlowchartNumberGuessWorkflow
Adicione o
CreateFlowchartUpdateMethod
a seguir à classeProgram
(ouModule1
). Esse método é semelhante aCreateStateMachineUpdateMap
. Começa com uma chamada paraStartUpdate
, atualiza a definição do fluxo de trabalho do fluxograma e conclui salvando o mapa de atualização e a definição atualizada do fluxo de trabalho.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"); }
Para atualizar SequentialNumberGuessWorkflow
Adicione o
CreateSequentialUpdateMethod
a seguir à classeProgram
(ouModule1
). Esse método é semelhante aos outros dois métodos. Começa com uma chamada paraStartUpdate
, atualiza a definição do fluxo de trabalho sequencial e conclui salvando o mapa de atualização e a definição atualizada do fluxo de trabalho.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"); }
Para compilar e executar o aplicativo CreateUpdateMaps
Atualize o método
Main
e adicione as três chamadas de método a seguir. Esses métodos são adicionados nas seções a seguir. Cada método atualiza o fluxo de trabalho de palpite de número correspondente e cria umDynamicUpdateMap
que descreve as atualizações.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(); }
Clique com o botão direito do mouse em CreateUpdateMaps no Gerenciador de Soluções e escolha Definir como projeto de inicialização.
Pressione CTRL+SHIFT+B para criar a solução, e CTRL+F5 para executar o aplicativo
CreateUpdateMaps
.Observação
O aplicativo
CreateUpdateMaps
não exibe nenhuma informação de status durante a execução, mas se você procurar na pasta NumberGuessWorkflowActivities_du e na pasta PreviousVersions, verá os arquivos de definição de fluxo de trabalho atualizados e os mapas de atualização.Assim que os mapas de atualização são criados e as definições de fluxo de trabalho são atualizadas, a próxima etapa é criar um assembly atualizado do fluxo de trabalho que contém as definições atualizadas.
Para criar o assembly de fluxo de trabalho atualizado
Abra uma segunda instância do Visual Studio 2012.
Escolha Abrir, Projeto/Solução no menu Arquivo.
Navegue até a pasta NumberGuessWorkflowActivities_du que você criou em Como: Hospedar várias versões de um fluxo de trabalho lado a lado, selecione NumberGuessWorkflowActivities.csproj (ou vbproj) e clique em Abrir.
No Gerenciador de Soluções, clique com o botão direito do mouse em SequentialNumberGuessWorkflow.xaml e escolha Excluir do projeto. Faça o mesmo para FlowchartNumberGuessWorkflow.xaml e StateMachineNumberGuessWorkflow.xaml. Esta etapa remove as versões anteriores das definições de fluxo de trabalho do projeto.
Escolha Adicionar item existente no menu Projeto.
Navegue até a pasta NumberGuessWorkflowActivities_du que você criou em Como: Hospedar várias versões de um fluxo de trabalho lado a lado.
Escolha Arquivos XAML (*.xaml;*.xoml) na lista suspensa Arquivos do tipo.
Selecione SequentialNumberGuessWorkflow_du.xaml, FlowchartNumberGuessWorkflow_du.xaml e StateMachineNumberGuessWorkflow_du.xaml e clique em Adicionar.
Observação
CTRL+Click para selecionar vários itens de cada vez.
Esta etapa adiciona as versões atualizadas das definições de fluxo de trabalho para o projeto.
Pressione CTRL+SHIFT+B para criar o projeto.
Escolha Fechar solução no menu Arquivo. Não é necessário um arquivo de solução para o projeto, então clique em Não para fechar o Visual Studio sem salvar um arquivo de solução. Escolha Sair no menu Arquivo para fechar o Visual Studio.
Abra o Windows Explorer e navegue até a pasta NumberGuessWorkflowActivities_du\bin\Debug (ou bin\Release dependendo das configurações do seu projeto).
Renomeie NumberGuessWorkflowActivities.dll para NumberGuessWorkflowActivities_v15.dll e copie-o para a pasta PreviousVersions que você criou em How to: Host Multiple Versions of a Workflow Side -a-lado.
Para atualizar WorkflowVersionMap com as novas versões
Volte para a instância inicial do Visual Studio 2012.
Clique duas vezes em WorkflowVersionMap.cs (ou WorkflowVersionMap.vb) no projeto NumberGuessWorkflowHost para abri-lo.
Adicione três novas identidades de fluxo de trabalho abaixo das seis declarações de identidade de fluxo de trabalho existentes. Neste tutorial,
1.5.0.0
é usado como oWorkflowIdentity.Version
para as identidades dinâmicas de atualização. Essas novas identidades de fluxo de trabalhov15
serão usadas para fornecer a definição correta do fluxo de trabalho para as instâncias de fluxo de trabalho persistidas atualizadas dinamicamente.'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;
Adicione o código a seguir no final do construtor. Esse código inicializa as identidades dinâmicos do fluxo de trabalho de atualização, carrega as definições de fluxo de trabalho correspondentes e adiciona-as ao dicionário de versão do fluxo de trabalho.
'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);
O exemplo a seguir é a classe
WorkflowVersionMap
concluída.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(); } }
Pressione CTRL+SHIFT+B para criar o projeto.
Para aplicar as atualizações dinâmicas
Clique com o botão direito do mouse em WF45GettingStartedTutorial no Gerenciador de Soluções e escolha Adicionar, Novo projeto.
No nó Instalado, selecione Visual C#, Windows (ou Visual Basic, Windows).
Observação
Dependendo da linguagem de programação que esteja configurada como linguagem primária no Visual Studio, o nó Visual C# ou Visual Basic poderá estar sob o nó Outras Linguagens no nó Instalado.
Certifique-se de que o .NET Framework 4.5 esteja selecionado na lista suspensa de versões do .NET Framework. Selecione Aplicativo de console na lista Windows. Digite ApplyDynamicUpdate na caixa Nome e clique em OK.
Clique com o botão direito do mouse em ApplyDynamicUpdate no Gerenciador de Soluções e escolha Adicionar Referência.
Clique em Solução e marque a caixa ao lado de NumberGuessWorkflowHost. Essa referência é necessária para que
ApplyDynamicUpdate
pode usar a classeNumberGuessWorkflowHost.WorkflowVersionMap
.Selecione Framework no nó Assemblies na lista Add Reference. Digite System.Activities na caixa Pesquisar assemblies. Isso filtrará os assemblies e facilitará a seleção das referências desejadas.
Marque a caixa de seleção ao lado de System.Activities na lista Resultados da pesquisa.
Digite Serialization na caixa Search Assemblies e marque a caixa de seleção ao lado de System.Runtime.Serialization na lista Search Results.
Digite DurableInstancing na caixa Search Assemblies e marque a caixa de seleção ao lado de System.Activities.DurableInstancing e System.Runtime.DurableInstancing no lista de Resultados de pesquisa.
Clique em OK para fechar o Gerenciador de referências e adicionar as referências.
Clique com o botão direito do mouse em ApplyDynamicUpdate no Gerenciador de Soluções e escolha Adicionar, Classe. Digite
DynamicUpdateInfo
na caixa Nome e clique em Adicionar.Adicionar os dois membros a seguir à classe
DynamicUpdateInfo
. O exemplo a seguir é a classeDynamicUpdateInfo
concluída. Esta classe contém informações sobre o mapa de atualização e a nova identidade de fluxo de trabalho usada quando uma instância de fluxo de trabalho é atualizada.Public Class DynamicUpdateInfo Public updateMap As DynamicUpdateMap Public newIdentity As WorkflowIdentity End Class
class DynamicUpdateInfo { public DynamicUpdateMap updateMap; public WorkflowIdentity newIdentity; }
Adicione as seguintes instruções
using
(ouImports
) na parte superior do arquivo com as outras instruçõesusing
(ouImports
).Imports System.Activities Imports System.Activities.DynamicUpdate
using System.Activities; using System.Activities.DynamicUpdate;
Clique duas vezes em Program.cs (ou Module1.vb) no Gerenciador de Soluções.
Adicione as seguintes instruções
using
(ouImports
) na parte superior do arquivo com as outras instruçõesusing
(ouImports
).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;
Adicionar o membro de cadeia de conexão a seguir à classe
Program
(ouModule1
).Const connectionString = "Server=.\SQLEXPRESS;Initial Catalog=WF45GettingStartedTutorial;Integrated Security=SSPI"
const string connectionString = "Server=.\\SQLEXPRESS;Initial Catalog=WF45GettingStartedTutorial;Integrated Security=SSPI";
Importante
A Microsoft recomenda usar o fluxo de autenticação mais seguro disponível. Se você estiver se conectando ao SQL do Azure, as Identidades gerenciadas para recursos do Azure é o método de autenticação recomendado.
Observação
Dependendo de sua edição do SQL Server, o nome do servidor da cadeia de conexão pode ser diferente.
Adicione o método
GetIDs
a seguir à classeProgram
(ouModule1
). Esse método retorna uma lista de ids de instância de fluxo de trabalho persistidas.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; }
Adicione o método
LoadMap
a seguir à classeProgram
(ouModule1
). Este método cria um dicionário que mapeia identidades de fluxo de trabalhov1
para os mapas de atualização e as novas identidades de fluxo de trabalho usadas para atualizar as instâncias de fluxo de trabalho correspondentes persistidas.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; }
Adicione o método
LoadMaps
a seguir à classeProgram
(ouModule1
). Esse método carrega os três mapas de atualização e cria um dicionário que mapeia identidades de fluxo de trabalhov1
para os mapas de atualização.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; }
Adicione o código a seguir a
Main
. Este código itera as instâncias de fluxo de trabalho persistidas e examina cadaWorkflowIdentity
. Se oWorkflowIdentity
mapeia para uma instância de fluxo de trabalhov1
, umWorkflowApplication
é configurado com a definição atualizada de fluxo de trabalho e uma identidade atualizada do fluxo de trabalho. Em seguida,WorkflowApplication.Load
é chamado com a instância e o mapa de atualização, que aplica o mapa de atualização dinâmica. Assim que a atualização é aplicada, a instância atualizada é persistida com uma chamada paraUnload
.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(); } }
Clique com o botão direito do mouse em ApplyDynamicUpdate no Gerenciador de Soluções e escolha Definir como projeto de inicialização.
Pressione Ctrl+Shift+B para criar a solução e pressione Ctrl+F5 para executar o aplicativo
ApplyDynamicUpdate
e atualizar as instâncias de fluxo de trabalho persistidas. Você deverá ver uma saída semelhante à seguinte. Os fluxos de trabalho da versão 1.0.0.0 são atualizados para a versão 1.5.0.0, enquanto que os fluxos de trabalho da versão 2.0.0.0 não são atualizados.Inspecionando: StateMachineNumberGuessWorkflow; Versão=1.0.0.0
Atualizado para: StateMachineNumberGuessWorkflow; Versão=1.5.0.0
Inspecionando: StateMachineNumberGuessWorkflow; Versão=1.0.0.0
Atualizado para: StateMachineNumberGuessWorkflow; Versão=1.5.0.0
Inspecionando: FlowchartNumberGuessWorkflow; Versão=1.0.0.0
Atualizado para: FlowchartNumberGuessWorkflow; Versão=1.5.0.0
Inspecionando: FlowchartNumberGuessWorkflow; Versão=1.0.0.0
Atualizado para: FlowchartNumberGuessWorkflow; Versão=1.5.0.0
Inspecionando: SequentialNumberGuessWorkflow; Versão=1.0.0.0
Atualizado para: SequentialNumberGuessWorkflow; Versão=1.5.0.0
Inspecionando: SequentialNumberGuessWorkflow; Versão=1.0.0.0
Atualizado para: SequentialNumberGuessWorkflow; Versão=1.5.0.0
Inspecionando: SequentialNumberGuessWorkflow; Versão=1.0.0.0
Atualizado para: SequentialNumberGuessWorkflow; Versão=1.5.0.0
Inspecionando: StateMachineNumberGuessWorkflow; Versão=1.0.0.0
Atualizado para: StateMachineNumberGuessWorkflow; Versão=1.5.0.0
Inspecionando: FlowchartNumberGuessWorkflow; Versão=1.0.0.0
Atualizado para: FlowchartNumberGuessWorkflow; Versão=1.5.0.0
Inspecionando: StateMachineNumberGuessWorkflow; Versão=2.0.0.0
Inspecionando: StateMachineNumberGuessWorkflow; Versão=2.0.0.0
Inspecionando: FlowchartNumberGuessWorkflow; Versão=2.0.0.0
Inspecionando: FlowchartNumberGuessWorkflow; Versão=2.0.0.0
Inspecionando: SequentialNumberGuessWorkflow; Versão=2.0.0.0
Inspecionando: SequentialNumberGuessWorkflow; Versão=2.0.0.0
Pressione qualquer tecla para continuar. . .
Para executar o aplicativo com os fluxos de trabalho atualizados
Clique com o botão direito do mouse em NumberGuessWorkflowHost no Gerenciador de Soluções e escolha Definir como projeto de inicialização.
Pressione CTRL+F5 para executar o aplicativo.
Clique em Novo jogo para iniciar um novo fluxo de trabalho e observe as informações da versão abaixo da janela de status que indica que o fluxo de trabalho é um fluxo de trabalho
v2
.Selecione um dos
v1
fluxos de trabalho iniciados no início do tópico Como: hospedar várias versões de um fluxo de trabalho lado a lado. Observe que as informações de versão na janela de status indicam que o fluxo de trabalho é um fluxo de trabalho de versão 1.5.0.0. Observe que não há informações indicada sobre os palpites anteriores além de se eram muito altos ou muito baixos.Insira um número entre 1 e 10
Seu palpite é muito baixo.Faça uma anotação da
InstanceId
e insira palpites até que o fluxo de trabalho seja concluído. A janela de status exibe informações sobre o conteúdo do palpite porque as atividadesWriteLine
foram atualizadas pela atualização dinâmica.Insira um número entre 1 e 10
Seu palpite é muito baixo.
Insira um número entre 1 e 10
5 é muito baixo.
Insira um número entre 1 e 10
7 é muito alto.
Insira um número entre 1 e 10
Parabéns, você acertou o palpite do número em 4 sequências.Abra o Windows Explorer e navegue até a pasta NumberGuessWorkflowHost\bin\debug (ou bin\release dependendo das configurações do seu projeto) e abra o arquivo de rastreamento usando o Bloco de Notas que corresponde ao fluxo de trabalho concluído. Se você não anotou o
InstanceId
, poderá identificar o arquivo de rastreamento correto usando as informações de Data de modificação no Windows Explorer. A última linha das informações de rastreamento contém a saída de atividade recém-adicionadaWriteLine
.Insira um número entre 1 e 10
Seu palpite é muito baixo.
Insira um número entre 1 e 10
5 é muito baixo.
Insira um número entre 1 e 10
7 é muito alto.
Insira um número entre 1 e 10
6 está correto. Você acertou o palpite em 4 sequências.
Para habilitar o início de versões anteriores dos fluxos de trabalho
Se você não tiver mais fluxos de trabalho para atualizar, poderá modificar o aplicativo NumberGuessWorkflowHost
para habilitar o início das versões anteriores dos fluxos de trabalho.
Clique duas vezes em WorkflowHostForm no Gerenciador de Soluções e selecione a caixa de combinação WorkflowType.
Na janela Propriedades, selecione a propriedade Itens e clique no botão de reticências para editar a coleção Itens.
Adicione os três itens a seguir à coleção.
StateMachineNumberGuessWorkflow v1 FlowchartNumberGuessWorkflow v1 SequentialNumberGuessWorkflow v1
A coleção de
Items
concluída terá seis itens.StateMachineNumberGuessWorkflow FlowchartNumberGuessWorkflow SequentialNumberGuessWorkflow StateMachineNumberGuessWorkflow v1 FlowchartNumberGuessWorkflow v1 SequentialNumberGuessWorkflow v1
Clique duas vezes em WorkflowHostForm no Gerenciador de Soluções e selecione Exibir código.
Adicione três novos casos à instrução
switch
(ouSelect Case
) no manipuladorNewGame_Click
para mapear os novos itens na caixa de combinação WorkflowType para as identidades de fluxo de trabalho correspondentes.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;
O exemplo a seguir contém a instrução completa de
switch
(ouSelect 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; };
Pressione CTRL+F5 para compilar e executar o aplicativo. Agora você pode iniciar as versões
v1
do fluxo de trabalho assim como as versões atuais. Para atualizar dinamicamente essas novas instâncias, execute o aplicativo ApplyDynamicUpdate.