[Stick to the top] Stick to learning WF Article Indexes
A large part of the workflow system needs to interact with people. Sometimes it takes a long time, so we cannot keep the workflow instance in the memory, which requires persistence. 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.
In Lotus Notes, because his design and data are stored in an NSF in the form of documents, he is born to support persistence, as long as we make a simple filesave or call Doc. save (True, true) will be permanently stored. In this case, we store a lot of information about the workflow status in each data file. net, Java, but it takes a lot of effort to complete the interaction with the DB and so on, the development of the two different styles is indeed quite interesting.
The persistence service is one of the core services in WF. The WF framework provides a standard persistence service, sqlworkflowpersistenceservice, which can store workflow status information in the SQL Server database, you can also implement the persistence service by yourself. You must inherit from the workflowpersistenceservice class. The custom persistence service can store data in binary files, XML files, and other relational databases, however, a workflow instance can only use one persistence service at a time.
Once you load the persistence service into the workflow engine, you do not need to manually interfere with it, and it will automatically complete the corresponding operations. In the following status, the workflow is persistent.
1. When idle is used (such as waiting for external events, use delayactivity ).
2. workflow completion or termination.
3. When transactionscopeactivity is completed.
4. When compensatablesequenceactivity is completed.
5. When a custom activity with persistoncloseattribute is completed.
6. When you manually call the unload or tryunload method.
If you use delayactivity, the persistence service will also store the expiration time of delayactivity, And the persistence service will regularly check whether it expires to prepare for resuming the workflow status, sqlworkflowpersistenceservice has a loadinginterval attribute to set the length of the loading interval.
Sometimes, when a workflow becomes an idle, you can choose not to store it persistently. This situation is suitable when you wait for external events frequently and the events will soon be received, at this time, if you are performing persistent storage, you will spend more time on unmounting and loading. It is better not to perform persistent storage.
The following example shows how to use sqlworkflowpersistenceservice:
1. First, we need to establish our persistent database. WF has provided the response SQL script in the following position:
[Windowsfolder] \ microsoft. Net \ framework \ V3.0 \ Windows Workflow Foundation \ SQL \ [language]. [windows] The sqlpersistenceservice_schema. SQL and sqlpersistenceservice_logic. SQL files are used to generate a persistent database.
The created Persistent Database contains two tables, instancestate and completedscope. The instancestate table records the running status of unfinished cases, and the completedscope table records the support for using transactions when a workflow is executed.
2. Define two events
2. 1. first define the ipersistencedemo interface:
[Externaldataexchange]Public InterfaceIpersistencedemo {EventEventhandler <externaldataeventargs> continuereceived;EventEventhandler <externaldataeventargs> stopreceived ;}
2. Implement the local service persistencedemoservice:
Public Class Persistencedemoservice: ipersistencedemo { Public Event Eventhandler <externaldataeventargs> continuereceived; Public Event Eventhandler <externaldataeventargs> stopreceived;Public Void Oncontinuereceived (externaldataeventargs ARGs ){ If (Continuereceived! = Null ) {Continuereceived ( Null , ArgS );}} Public Void Onstopreceived (externaldataeventargs ARGs ){ If (Stopreceived! = Null ) {Stopreceived ( Null , ArgS );}}}
3. Implement a workflow, such:
3.1.whileactivity is a condition! This. iscomplete
3.2.heecontinue and heestop receive the continuereceived and stopreceived events we have defined.
CodeAs follows:
Public Sealed Partial Class Persistencedemoworkflow: sequentialworkflowactivity { Private Boolean iscomplete = False ; Public Boolean iscomplete { Get { Return Iscomplete ;} Set {Iscomplete = Value ;}} Public Persistencedemoworkflow () {initializecomponent ();} Private Void Handlestopreceived_invoked ( Object Sender, externaldataeventargs e ){ // Tell the whileactivity to stop Iscomplete = True ;}}
4. Implement the hostProgram
. First, add a class to display the workflow status.
Public Class Workflow { Private Guid instanceid = guid. empty; Private String statusmessage = string. empty; Private Boolean iscompleted; Public Guid instanceid { Get { Return Instanceid ;} Set {Instanceid = Value ;}} Public String statusmessage { Get {Return Statusmessage ;} Set {Statusmessage = Value ;}} Public Boolean iscompleted { Get { Return Iscompleted ;} Set {Iscompleted = Value ;}}}
. This time we use a Windows form program. The result is as follows:
After creating a workflow instance, we can see that its statusmessage changes from created-ilded-persisted-unloaded.
When the stream is executed in the listenactivity waiting for the event, the status of the period Changes to ilded. When the ilded event is executed, the status information of the workflow instance will be stored persistently.
When the SQL data is stored, the state changes from persisted to unloaded. It does not matter even if you close the program. If you click the continue button,
Statusmessage is changed to loaded-ilded-persisted-unloaded. It loads the persistent workflow from the database and click STOP.
It will change to the completed status.
After persistence, we close the application and call the following method to load all workflow instances when rewriting and opening. getallworkflows is mainly used to obtain
All workflow instances.
Private VoidRetrieveexistingworkflows () {workflows. Clear ();Foreach(Sqlpersistenceworkflowinstancedescription workflowdescIn(Sqlworkflowpersistenceservice) persistence). getallworkflows () {workflow =NewWorkflow (); workflow. instanceid = workflowdesc. workflowinstanceid; workflow. statusmessage ="Unloaded"; Workflows. Add (workflow. instanceid, workflow );}If(Workflows. Count> 0) {refreshdata ();}}
In the host Program, we define the following method to load sqlworkflowpersistenceservice and the local service, sqlworkflowpersistenceservice
The usage of some member methods of the class is poor,
Private Void Addservices (workflowruntime instance ){ // Use the standard SQL Server persistence service String connstringpersistence = string. Format (" Initial catalog = {0}; Data Source = {1}; Integrated Security = {2 }; "," Workflowpersistence ",@" Localhost \ sqlexpress "," Sspi "); Persistence = New Sqlworkflowpersistenceservice (connstringpersistence, True , New Timespan (0, 2, 0 ),New Timespan (0, 0, 5); instance. addservice (persistence ); // Add the external data exchange service to the runtime Externaldataexchangeservice exchangeservice = New Externaldataexchangeservice (); instance. addservice (exchangeservice ); // Add our local service Persistencedemoservice = New Persistencedemoservice (); exchangeservice. addservice (persistencedemoservice );}
Other code basically changes automatically around the implementation of statusmessage, and has little to do with the workflow.
Download Code: persistencedemo