Post navigation

Updating workflow instances using an update map

One of the really important new features in Windows Workflow Foundation 4.5 is the capability to version workflows and workflow instances. You get to choose what you want to do, either keep running existing instances with their original workflow definition or upgrade them to the latest workflow definition.

What should you do, upgrade exiting instances or run multiple definitions side by side?

Both the upgrade to latest and keep running with the original definition make sense in different scenarios. If you find a bug in your workflow definition the update scenario is probably what you are looking for. However if your business contract conditions change it makes sense to keep the older workflow instances with the original workflow definition and start new new workflows with the new definition. Both make sense, it’s just a matter of the requirements.

In this blog post I am going to explain how to do an upgrade of an existing workflow instance. In a future blog post I will go into side by side execution.

The basic steps

When upgrading a workflow instance we are always concerned with the following basic steps”

Create your initial workflow definition.

Start one or more instances using the this workflow definition.

Prepare the original workflow definition for update.

Make some changes to the workflow definition.

Create an update map between the original workflow definition and the new one.

Update exiting workflow instances to reflect the new workflow definition.

Create your initial workflow definition

This is the simple step as anyone that has been using Windows Workflow Foundation 4 has already been doing this. For this example I am using a real simple workflow that prints the version number it was started with and the current version.

One thing that is new here is associating a version with this workflow. When I create an instance of the WorkflowApplication I am using a WorkflowIdentity with a version of 1.0.

1:privatestatic WorkflowApplication CreateWorkflowApplication()

2: {

3: var identity = new WorkflowIdentity

4: {

5: Version = new Version(1, 0)

6: };

7:

8: var workflow = new TheWorkflow();

9: var app = new WorkflowApplication(workflow, identity);

10: app.InstanceStore = CreateSqlWorkflowInstanceStore();

11: app.PersistableIdle = e => PersistableIdleAction.Persist;

12: app.OnUnhandledException = e =>

13: {

14: Console.WriteLine(e.UnhandledException.Message);

15:return UnhandledExceptionAction.Abort;

16: };

17:

18:return app;

19: }

Start one or more instances using the this workflow definition

Again no big deal here, just run the workflow application.

1:privatestaticvoid StartNewWorkflow()

2: {

3: WorkflowApplication app = CreateWorkflowApplication();

4: app.Run();

5: }

Prepare the original workflow definition for update

In this step we prepare the workflow definition, the XAML file, for update using the DynamicUpdateServices.PrepareForUpdate() on an ActivityBuilder. This step adds a copy of the workflow definition in a DynamicUpdateInfo.OriginalActivityBuilder element so we can see the differences later when we are done. Right now we can use the workflow to run a workflow and everything would appear unchanged.

Unhandled Exception: System.Activities.VersionMismatchException: The WorkflowIdentity (‘; Version=1.0’) of the loaded instance does not match the WorkflowIdentity (‘; Version=1.1’) of the provided workflow definition. The instance can be loaded using a different definition, or updated using Dynamic Update.

Create an update map between the original workflow definition and the new one

In order to upgrade the saved workflow instance we first need to create an update map. In this step we use the DynamicUpdateServices.CreateUpdateMap() function to create a map of the changes made since DynamicUpdateServices.PrepareForUpdate() was called. There is no way to create an update map based on anything else then the internal DynamicUpdateInfo. This means if you forgot to call DynamicUpdateServices.PrepareForUpdate() and save the workflow but instead just started making changes you are going to experience some problems. My first expectation was I could create an update map by comparing and older version of the workflow, for example from the TFS history, but that just isn’t possible using DynamicUpdateServices.CreateUpdateMap(). One solution here might be to use DynamicUpdateInfo.SetOriginalActivityBuilder().

Another slightly surprising thing is there is no native save functionality for a DynamicUpdateMap. In this case I am using a DataContractSerializer to save the update map in a way I can load it again.

Update exiting workflow instances to reflect the new workflow definition

With the update map in place we can finally go and update workflow instances saved in the instance store. The code isn’t hard, just load the workflow instance using WorkflowApplication.Load() passing in the DynamicUpdateMap to use, make sure to unload the workflow again and you are good to go.

As you can see the workflow state still contains the reference to version 1.0 from when it started but the current workflow definition used is 1.1.

Of course there are changes that might be impossible to make, for example deleting the currently executing activity would leave the workflow in an invalid state. Using the WorkflowApplicationInstance.CanApplyUpdate() function you can check if an update is actually possible before doing so.

Great tutorial. I have one question though. Is it possible to use update maps with Workflow Services(.xamlx)? I have been looking allover the net and mostly found examples with .xaml files or unanswered questions related to .xamlx files. If it is possible, could you do a step by step example the same as this one?

Than you for the great article. Currently working on Workflow Services(.xamlx)? I have been looking allover the net and mostly found examples with .xaml files or unanswered questions related to .xamlx files. If it is possible, could you do a step by step example the same as this one?