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 de fluxo de trabalho persistente. 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 v1
fluxo de trabalho de adivinhação de números para corresponder à nova funcionalidade introduzida 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).
Nota
Dependendo de qual linguagem de programação é configurada como a linguagem principal no Visual Studio, o nó Visual C# ou Visual Basic pode estar sob o nó Outras linguagens no nó instalado .
Verifique se o .NET Framework 4.5 está selecionado na lista suspensa de versão 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 Adicionar Referência.
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 Resultados da Pesquisa.
Digite System.Xaml na caixa Assemblies de Pesquisa 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
using
(ouImports
) instruções na parte superior do arquivo com as outrasusing
(ouImports
) instruções.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;
Adicione os seguintes dois membros de cadeia de caracteres à
Program
classe (ouModule1
).Const mapPath = "..\..\..\PreviousVersions" Const definitionPath = "..\..\..\NumberGuessWorkflowActivities_du"
const string mapPath = @"..\..\..\PreviousVersions"; const string definitionPath = @"..\..\..\NumberGuessWorkflowActivities_du";
Adicione o seguinte
StartUpdate
método àProgram
classe (ouModule1
). Esse método carrega a definição de fluxo de trabalho xaml especificada em umActivityBuilder
e, em seguida, chamaDynamicUpdate.PrepareForUpdate
.PrepareForUpdate
faz uma cópia da definição de fluxo de trabalho dentro doActivityBuilder
. Depois que a definição do fluxo de trabalho é modificada, essa cópia é usada junto com a definição de fluxo de trabalho modificada 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 seguinte
CreateUpdateMethod
àProgram
classe (ouModule1
). Isso cria um mapa de atualização dinâmico chamando DynamicUpdateServices.CreateUpdateMap e, em seguida, salva o mapa de atualização usando o nome especificado. Este mapa de atualização contém as informações necessárias para o tempo de execução do fluxo de trabalho atualizar uma instância de fluxo de trabalho persistente que foi iniciada usando a definição de fluxo de trabalho original contida noActivityBuilder
para que seja concluída usando a definição de fluxo de trabalho atualizada.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 seguinte
SaveUpdatedDefinition
método àProgram
classe (ouModule1
). Esse método salva a definição de fluxo de trabalho atualizada assim que 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
àProgram
classe (ouModule1
).Private Sub CreateStateMachineUpdateMap() End Sub
private static void CreateStateMachineUpdateMap() { }
Faça uma chamada para e, em
StartUpdate
seguida, obtenha 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
WriteLine
atividades que exibem se o palpite do usuário é muito alto ou muito baixo 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
WriteLine
atividade 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 for atualizado, chame
CreateUpdateMaps
eSaveUpdatedDefinition
.CreateUpdateMaps
cria e salva oDynamicUpdateMap
, eSaveUpdatedDefinition
salva a definição de fluxo de trabalho atualizada.'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 complete
CreateStateMachineUpdateMap
.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 o FlowchartNumberGuessWorkflow
Adicione o seguinte
CreateFlowchartUpdateMethod
àProgram
classe (ouModule1
). Este método é semelhante aoCreateStateMachineUpdateMap
. Ele começa com uma chamada paraStartUpdate
, atualiza a definição do fluxo de trabalho do fluxograma e termina salvando o mapa de atualização e a definição do fluxo de trabalho atualizado.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 o SequentialNumberGuessWorkflow
Adicione o seguinte
CreateSequentialUpdateMethod
àProgram
classe (ouModule1
). Este método é semelhante aos outros dois métodos. Ele começa com uma chamada paraStartUpdate
, atualiza a definição de fluxo de trabalho sequencial e termina salvando o mapa de atualização e a definição de fluxo de trabalho atualizada.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 criar e executar o aplicativo CreateUpdateMaps
Atualize o
Main
método 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 adivinhação 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, em seguida, CTRL+F5 para executar o
CreateUpdateMaps
aplicativo.Nota
O
CreateUpdateMaps
aplicativo não exibe nenhuma informação de status durante a execução, mas se você olhar 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.Depois que os mapas de atualização são criados e as definições de fluxo de trabalho atualizadas, a próxima etapa é criar um assembly de fluxo de trabalho atualizado contendo 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 a mesma coisa 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.
Nota
CTRL+Clique para selecionar vários itens ao mesmo tempo.
Esta etapa adiciona as versões atualizadas das definições de fluxo de trabalho ao projeto.
Pressione CTRL+SHIFT+B para criar o projeto.
Escolha Fechar solução no menu Arquivo . Um arquivo de solução para o projeto não é necessário, portanto, 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 projeto).
Renomeie NumberGuessWorkflowActivities.dll para NumberGuessWorkflowActivities_v15.dll e copie-o para a pasta PreviousVersions que você criou em Como: Hospedar várias versões de um fluxo de trabalho lado a lado.
Para atualizar o 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) sob o projeto NumberGuessWorkflowHost para abri-lo.
Adicione três novas identidades de fluxo de trabalho logo 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 de atualização dinâmica. Essas novasv15
identidades de fluxo de trabalho serão usadas para fornecer a definição correta do fluxo de trabalho para as instâncias de fluxo de trabalho persistentes 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 seguinte código no final do construtor. Esse código inicializa as identidades do fluxo de trabalho de atualização dinâmica, carrega as definições de fluxo de trabalho correspondentes e as adiciona 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 completed
WorkflowVersionMap
.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).
Nota
Dependendo de qual linguagem de programação é configurada como a linguagem principal no Visual Studio, o nó Visual C# ou Visual Basic pode estar sob o nó Outras linguagens no nó instalado .
Verifique se o .NET Framework 4.5 está selecionado na lista suspensa de versão 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
possa usar aNumberGuessWorkflowHost.WorkflowVersionMap
classe.Selecione Framework no nó Assemblies na lista Add Reference . Digite System.Activities na caixa Search Assemblies . Isso filtrará os assemblies e tornará as referências desejadas mais fáceis de selecionar.
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 Resultados da Pesquisa.
Digite DurableInstancing na caixa Search Assemblies e marque a caixa de seleção ao lado de System.Activities.DurableInstancing e System.Runtime.DurableInstancing na lista Resultados da 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.Adicione os dois membros a seguir à
DynamicUpdateInfo
classe. O exemplo a seguir é a classe completedDynamicUpdateInfo
. Essa classe contém informações sobre o mapa de atualização e a nova identidade do fluxo de trabalho usada quando uma instância do 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
using
(ouImports
) instruções na parte superior do arquivo com as outrasusing
(ouImports
) instruções.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
using
(ouImports
) instruções na parte superior do arquivo com as outrasusing
(ouImports
) instruções.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;
Adicione o seguinte membro da cadeia de conexão à
Program
classe (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 que você use 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 serão o método de autenticação recomendado.
Nota
Dependendo da sua edição do SQL Server, o nome do servidor da cadeia de conexão pode ser diferente.
Adicione o seguinte
GetIDs
método àProgram
classe (ouModule1
). Esse método retorna uma lista de ids de instância de fluxo de trabalho persistente.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 seguinte
LoadMap
método àProgram
classe (ouModule1
). Esse método cria um dicionário que mapeiav1
identidades de fluxo de trabalho para os mapas de atualização e novas identidades de fluxo de trabalho usadas para atualizar as instâncias de fluxo de trabalho persistentes correspondentes.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 seguinte
LoadMaps
método àProgram
classe (ouModule1
). Esse método carrega os três mapas de atualização e cria um dicionário que mapeiav1
identidades de fluxo de trabalho 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 seguinte código a
Main
. Esse código itera as instâncias de fluxo de trabalho persistentes e examina cadaWorkflowIdentity
uma delas. Se o mapeiaWorkflowIdentity
para umav1
instância de fluxo de trabalho, aWorkflowApplication
é configurado com a definição de fluxo de trabalho atualizada e uma identidade de fluxo de trabalho atualizada. Em seguida,WorkflowApplication.Load
é chamado com a instância e o mapa de atualização, que aplica o mapa de atualização dinâmica. Depois que a atualização é aplicada, a instância atualizada é mantida 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, em seguida, pressione Ctrl+F5 para executar o
ApplyDynamicUpdate
aplicativo e atualizar as instâncias de fluxo de trabalho persistentes. Deverá ver um resultado semelhante ao seguinte. Os fluxos de trabalho da versão 1.0.0.0 são atualizados para a versão 1.5.0.0, enquanto 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
Inspeção: FlowchartNumberGuessWorkflow; Versão=1.0.0.0
Atualizado para: FlowchartNumberGuessWorkflow; Versão=1.5.0.0
Inspeção: FlowchartNumberGuessWorkflow; Versão=1.0.0.0
Atualizado para: FlowchartNumberGuessWorkflow; Versão=1.5.0.0
Inspeção: SequentialNumberGuessWorkflow; Versão=1.0.0.0
Atualizado para: SequentialNumberGuessWorkflow; Versão=1.5.0.0
Inspeção: SequentialNumberGuessWorkflow; Versão=1.0.0.0
Atualizado para: SequentialNumberGuessWorkflow; Versão=1.5.0.0
Inspeção: 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
Inspeção: 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
Inspeção: FlowchartNumberGuessWorkflow; Versão=2.0.0.0
Inspeção: FlowchartNumberGuessWorkflow; Versão=2.0.0.0
Inspeção: SequentialNumberGuessWorkflow; Versão=2.0.0.0
Inspeção: 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.
Prima CTRL+F5 para executar a aplicação.
Clique em Novo Jogo para iniciar um novo fluxo de trabalho e anote as informações de versão abaixo da janela de status que indica que o fluxo de trabalho é um fluxo de
v2
trabalho.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 da versão 1.5.0.0 . Observe que não há nenhuma informação indicada sobre suposições anteriores além de se elas eram muito altas ou muito baixas.Introduza um número entre 1 e 10
Seu palpite é muito baixo.Anote o e, em
InstanceId
seguida, insira suposições até que o fluxo de trabalho seja concluído. A janela de status exibe informações sobre o conteúdo da suposição porque asWriteLine
atividades foram atualizadas pela atualização dinâmica.Introduza um número entre 1 e 10
Seu palpite é muito baixo.
Introduza um número entre 1 e 10
5 é muito baixo.
Introduza um número entre 1 e 10
7 é muito alto.
Introduza um número entre 1 e 10
Parabéns, você adivinhou o número em 4 voltas.Abra o Windows Explorer e navegue até a pasta NumberGuessWorkflowHost\bin\debug (ou bin\release , dependendo das configurações do projeto) e abra o arquivo de acompanhamento usando o Bloco de Notas que corresponde ao fluxo de trabalho concluído. Se você não fez uma anotação do
InstanceId
você pode ser capaz de identificar o arquivo de controle correto usando as informações de data modificada no Windows Explorer. A última linha das informações de rastreamento contém a saída da atividade recém-adicionadaWriteLine
.Introduza um número entre 1 e 10
Seu palpite é muito baixo.
Introduza um número entre 1 e 10
5 é muito baixo.
Introduza um número entre 1 e 10
7 é muito alto.
Introduza um número entre 1 e 10
6 está correto. Você adivinhou em 4 voltas.
Para habilitar o início de versões anteriores dos fluxos de trabalho
Se você ficar sem fluxos de trabalho para atualizar, poderá modificar o aplicativo para habilitar o NumberGuessWorkflowHost
início de 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 Items e clique no botão de reticências para editar a coleção Items.
Adicione os três itens a seguir à coleção.
StateMachineNumberGuessWorkflow v1 FlowchartNumberGuessWorkflow v1 SequentialNumberGuessWorkflow v1
A coleção completa
Items
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 à
switch
instrução (ouSelect Case
) noNewGame_Click
manipulador 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
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
v1
versões do fluxo de trabalho, bem como as versões atuais. Para atualizar dinamicamente essas novas instâncias, execute o aplicativo ApplyDynamicUpdate .