Workflow persistence stores certain State information of a workflow to persistent storage, such as SQL databases and files. Once saved to persistent storage, the workflow can be removed from the memory, load as needed.
WF persistence service
The WF runtime engine provides a series of underlying function libraries for executing and managing workflow lifecycles. The runtime engine architecture is highly scalable. For example, the runtime architecture can host any type of Windows process, rather than a specified type of host. More importantly, most features of the runtime engine are implemented in the form of a separate RunTime "service", which is easy to customize. (Mic: You can use WorkflowRuntime. addService method to add the corresponding service) In fact, developers can easily add/delete various services to the runtime engine; and by using the WF library, developers can create their own runtime services.
By default, the workflow Host Program executes workflow instances in the memory without any maintenance work. In many scenarios, for example, a long-term running process (BPM, I mentioned in the previous post) requires a mechanism to persist the workflow state during execution. In WF terminology, persistent workflows to persistent media are called dehydration.
In WF, persistence uses a runtime service. The main function of this service is to save/restore a certain state of the workflow to/from a persistent media. WF provides a default persistence service: SQLStatePersistenceService (Mic: it is estimated that most people will not use it J). However, with a scalable runtime service model, developers can choose to create their own persistence services. This is explained below:
The following is an ordered workflow demo, which consists of three activities:
Activity
Activity Type
Function
Before Serialize
Code
Prints the phrase "Before Serialize" to the console
Delay1
Delay
Suspends the workflow execution for a period of 50 seconds
After Serialize
Code
Prints the phrase "After Serialize" to the console
Configure the persistence service now:
1. Create and configure a Persistent Database
2. Add the SQLStatePersistanceService instance object to the WorkFlow Runtime (as I have mentioned earlier)
3. Save the workflow instance status.
The first is not described. The second is a simple introduction. There are two main methods: the first one I have mentioned earlier, and the second one is to add the following to the configuration file:
<WorkflowRuntime UnloadOnIdle = "true">
<Services>
<Add ConnectionString = "Data Source = localhost; Initial Catalog = WFState; Integrated Security = True;"/>
</Services>
</WorkflowRuntime>
Once the persistence service is added to the workflow runtime engine, it gradually persists the workflow instance status to the persistent media. There are two methods:
1. Force workflow instance Persistence: Call the Unload method of the workflow instance. By default, this method uses the associated persistence service to remove the workflow instance from the memory and save its status.
2. Another method is to enable persistent instance status when the workflow is running in an idle state. However, you must set the UnLoadOnIdle attribute to true. This setting must be performed before the StartRuntime method is called. Similar to this:
WorkflowRuntime. UnloadOnIdle = true;
WorkflowRuntime. StartRuntime ();
The workflow is implemented by calling the SaveWorkflowInstanceState method of the persistence service. This is a virtual method. At the same time, StatePersistenceService is the base class of all persistent service classes.
Restore persistent data from persistent media
The WF runtime engine can restore workflow instances to the memory to allow continued execution as planned. One way is to call the Load method of the workflow instance. The runtime engine can also beToIdleTimeRestore a workflow instance.
Another method is to explicitly interact with the persistent service. In this way, the GetWorkflow and Loads methods of the WorkflowRuntime class must be called.
Suppose a scenario: When an idle state is reached, the state of the persistent workflow instance is told during Workflow running, and the execution of the stream is suspended immediately when it reaches the After_Serialize code activity. At this time, we can query the InstanceState table in the database to obtain the serialization status.
SELECT uidInstanceID, state
FROM InstanceState
If we then restore the instance using the code below we will ge the following output, "After Serialize ...".
WorkflowRuntime = new WorkflowRuntime ();
WorkflowRuntime. AddService (new SqlStatePersistenceService ("Data Source = localhost; Initial Catalog = WFState; Integrated Security = True ");
WorkflowRuntime. AddService (new SqlTimerService ("Data Source = localhost; Initial Catalog = WFState; Integrated Security = True "));
WorkflowRuntime. StartRuntime ();
CurrentInstance = workflowRuntime. GetWorkflow (new Guid ("DC466C9E-5285-4D88-A9A2-FB79EAF81360 ″));
CurrentInstance. Load ();
Develop custom persistence services
1: public class FilePersistenceProvider: StatePersistenceService
2 :{
3: public FilePersistenceProvider (string basedir)
4 :{
5: FBaseDir = basedir;
6 :}
7:
8: private string FBaseDir;
9: public override void SaveWorkflowInstanceState (Activity rootActivity, bool unlock)
10 :{
11: ActivityExecutionContextInfo contextInfo = (ActivityExecutionContextInfo) rootActivity. GetValue (Activity. ActivityExecutionContextInfoProperty );
12: SerializeActivity (rootActivity, contextInfo. ContextGuid );
13 :}
14:
15: // load workflow instance state
16: public override Activity LoadWorkflowInstanceState (Guid instanceId)
17 :{
18: object obj = DeserializeActivity (null, instanceId );
19: return (Activity) obj;
20 :}
21: // unlock workflow instance state.
22: // instance state locking is necessary when multiple runtimes share instance persistence store
23: public override void UnlockWorkflowInstanceState (Activity state)
24 :{
25: // not implemented...
26 :}
27:
28: // save completed scope activity state
29: public override void SaveCompletedContextActivity (Activity rootActivity)
30 :{
31: ActivityExecutionContextInfo contextInfo = (ActivityExecutionContextInfo) rootActivity. GetValue (Activity. ActivityExecutionContextInfoProperty );
32: SerializeActivity (rootActivity, contextInfo. ContextGuid );
33 :}
34:
35: // Load completed scope activity state.
36: public override Activity LoadCompletedContextActivity (Guid activityId, Activity outerActivity)
37 :{
38: object obj = DeserializeActivity (outerActivity, activityId );
39: return (Activity) obj;
40 :}
41:
42: private void SerializeActivity (Activity RootActivity, Guid id)
43 :{
44: string filename = FBaseDir + "\" + id. ToString () + ". bin ";
45: FileStream stream = new FileStream (filename, FileMode. OpenOrCreate );
46: RootActivity. Save (stream );
47: stream. Close ();
48 :}
49:
50: private object DeserializeActivity (Activity RootActivity, Guid id)
51 :{
52: string filename = FBaseDir + "\" + id. ToString () + ". bin ";
53: FileStream stream = new FileStream (filename, FileMode. Open );
54: object Result = Activity. Load (stream, RootActivity );
55: return Result;
56 :}
57 :}
It should be emphasized that:
StatePersistenceServiceIt is the base class of all persistent workflow services. After a Custom Service class inherits from it, it can call a custom persistence method through some corresponding override methods.
From: http://www.mulongtec.com/blog/index.php/archives/114