We've been using the Workflow Foundation for our latest project, originally loving the idea of being able to design the workflow graphically, figuring this would make the program more maintainable and easier to explain. We were half right, it is easier to explain. However, we soon found that there were many aspects of workflow that, in my opinion, greatly reduced it's maintainability.
First, Workflow Foundation's designer is painfully slow. It's okay if you only have a few activities, but one of our workflows has dozens of activities, between actions which can be fired, and the various states of an instance. This is bad enough, given that it can take almost ten minutes to make even a simple change to the workflow, but oddly, it's not what I find the most frustrating part of working with workflow. That, needs to go to just how fragile workflow is. The way workflow persistence works is that it saves an exact copy of a workflow instance to...something. We use the database, using the provided SqlWorkflowPersistenceService.
Persistence is important, and I suspect that almost every single case where Workflow is going to be used, Persistence will be a necessary function. In our case, however, we don't keep any important data solely in the workflow instances, because we want to provide data visualization and reporting that we simply couldn't do effectively if we needed to dig into each worklow instance individually. In short, we have no good apparent reason to need to use the 'standard' SQL Persistence Service. With that in mind, I began digging into writing a custom Persistence Service.
The beginning seems simple enough, extend the WorkflowPersistenceService Class, and implement abstract methods which it declares. However, I've run into some serious issues. Workflow does not provide a good mechanism for re-instantiating a workflow instance. Ruurd Boeke provided a good example of rebuilding the workflows when the base class changed, which we've implemented, but it takes nearly 3 hours to perform on our data set (we have 2800+ workflows active). Needless to say, this is not an ideal situation, and our hope is that a custom Persistence Service will solve it.
Creating a new instance to return is simple enough, the WorkflowPersistenceService class provides access to the current WorkflowRuntime, and you can simple call the runtime's CreateWorkflow method, proving the dictionary of Properties to set, and the GUID you want applied to the instance. However, I have been unable to force the workflow instance into the correct state. Boeke's method is as follows:
StateMachineWorkflowInstance statemachine = new StateMachineWorkflowInstance(runtime, instanceGUID); statemachine.SetState(newWF.DefineNewStateAfterUpdate(oldWF.CurrentStateName));
This is impossible to use, simple because the the StateMachineWorkflowInstance constructor attempts to instantiate the Workflow instance identified by the GUID from the persistence store. And, even when you are creating a workflow instance which is a State Machine, you can not coerce it into this type, as a StateMachineWorkflowInstance is not a subclass of WorkflowInstance. I'm curious why that is.
Why is this so difficult? Microsoft seems to assume that you would only want to ever serialize the object to persist it. Every example of Workflow Persistence I've found uses that code. Since it wasn't made easy, I'm currently digging through the objects in the debugger, trying to figure out what all I need to set (and to what) in order to create a workflow instance which is usable.
Barring that, I'll probably make the workflow rebuilding code available to the service so that if a workflow instance fails to instantiate, I can just recreate it on the fly. This way, I still can upgrade my workflows when necessary, but I don't need to take the site down for several hours to accomplish it.
If anyone has any idea on how to set the workflow state from just the workflow instance, I'd love to know. Whichever solution I arrive at, I'll likely post a better description of what I consider the best way to accomplish this, but at the moment I'm annoyed, because once more I've encountered a Microsoft technology that completely fails to acknowledge a use case outside of what they consider 'nominal'. I can not figure out why Microsoft would design a workflow system which made it difficult to upgrade. I can not figure out why they offer the ability to write a persistence store, but only offer or discuss a single method of persisting the actual objects.
The next version of Workflow, which probably will hit with Visual Studio 2010 is supposed to fix a lot of things, though I have concerns about how much they'll fix (the designer is getting completely reworked, so that might be nice). But I would be leery about recommending people use Workflow Foundation at this time. It's a great idea, like most of these proposed systems are, but there are a lot of maintenance headaches about using these systems that I wish we'd been aware of six months ago.