坚持学习WF(13):WF中的持久化服务
2008-06-25 07:52
537 查看
工作流系统中有很大一部分需要和人进行交互,有的时候需要很长的时间,所以我们不可能让工作流实例一直保存在内存当中,这就需要进行持久化操作。工作流的持久化就是保存工作流的某些状态信息到持久化存储里,比如sql数据库,文件中,一旦被保存到持久化存储里了,工作流就可以从内存中移除掉,在需要的时候在进行装载。
插一句,在LotusNotes中由于他的设计和数据都是以文档的形式存储在一个nsf中的,所以他天生就对持久化支持,只要我们做简单的做一个FileSave或是Calldoc.Save(True,True)就会被持久存储,也正是如此,我们很多关于工作流的状态信息我们都存储在每个数据文档本身当中,可在.Net,Java这些当中却还需要花费很大的力气和DB等交互才可以完成,两种不同风格的开发对比起来确实挺有意思。
持久化服务是WF中核心服务之一,WF框架提供一个标准的持久化服务SqlWorkflowPersistenceService,利用它可以将工作流状态信息存放在SqlServer数据库中,你也可以自己实现持久化服务,你必须继承自WorkflowPersistenceService这个类,自定义的持久化服务可以把数据存储在二进制文件,xml,其他关系型数据库中等等,但是一个工作流实例一次只能使用一个持久化服务。
一旦你将持久化服务加载到工作流引擎中,你就不需要手动去干涉了,他会自动的完成相应的操作。在以下状态的时候,工作流会被持久化。
1.idle的时候(如等待外部事件,使用DelayActivity)。
2.工作流完成或终止。
3.当TransactionScopeActivity完成的时候。
4.当CompensatableSequenceActivity完成的时候。
5.当一个装饰有PersistOnCloseAttribute的自定义活动完成的时候。
6.当你手动的去调用Unload或TryUnload方法的时候。
如果你使用DelayActivity的时候,持久化服务也会存储DelayActivity的过期时间,并且持久化服务会定期检查是否过期,以准备从新恢复工作流状态,SqlWorkflowPersistenceService有一个LoadingInterval属性可以设置获取加载间隔的长度。
有的时候当工作流变成idle的时候,你也可以选择不进行持久化存储,这种情况适合当你等待的外部事件比较频繁,而且事件很快就被接收的时候,因为这个时候如果你在进行持久化存储,你花在卸载和装载上时间会更多,还不如不进行持久化存储呢。
下面我们完成一个例子来说如何使用SqlWorkflowPersistenceService:
1.首先我们需要建立我们的持久化数据库,WF已提供了响应sql脚本,位置如下:
[WindowsFolder]\Microsoft.Net\Framework\v3.0\WindowsWorkflowFoundation\SQL\[language].[windows]这里面有SqlPersistenceService_Schema.sql和SqlPersistenceService_Logic.sql两个文件用来生成持久化数据库.
创建好的持久化数据库里包含两张表,InstanceState和CompletedScope,InstanceState表中记录未完成事例的运行状态,CompletedScope表记录当工做流使用事务的支持。
2.定义两个事件
2.1.首先定义IPersistenceDemo接口:
[ExternalDataExchange] publicinterfaceIPersistenceDemo { eventEventHandler<ExternalDataEventArgs>ContinueReceived; eventEventHandler<ExternalDataEventArgs>StopReceived; }
2.2.实现本地服务PersistenceDemoService:
publicclassPersistenceDemoService:IPersistenceDemo { publiceventEventHandler<ExternalDataEventArgs>ContinueReceived; publiceventEventHandler<ExternalDataEventArgs>StopReceived; publicvoidOnContinueReceived(ExternalDataEventArgsargs) { if(ContinueReceived!=null) { ContinueReceived(null,args); } } publicvoidOnStopReceived(ExternalDataEventArgsargs) { if(StopReceived!=null) { StopReceived(null,args); } } }
3.实现工作流,如下图:
3.1.whileActivity的条件为!this.IsComplete
3.2.heeContinue和heeStop分别接收我们定义的ContinueReceived和StopReceived事件。
代码如下:
publicsealedpartialclassPersistenceDemoWorkflow:SequentialWorkflowActivity
{
privateBooleanisComplete=false;
publicBooleanIsComplete
{
get{returnisComplete;}
set{isComplete=value;}
}
publicPersistenceDemoWorkflow()
{
InitializeComponent();
}
privatevoidhandleStopReceived_Invoked(objectsender,ExternalDataEventArgse)
{
//telltheWhileActivitytostop
isComplete=true;
}
}
4.实现宿主程序 4.1.首先增加一个类来显示工作流状态
publicclassWorkflow
{
privateGuidinstanceId=Guid.Empty;
privateStringstatusMessage=String.Empty;
privateBooleanisCompleted;
publicGuidInstanceId
{
get{returninstanceId;}
set{instanceId=value;}
}
publicStringStatusMessage
{
get{returnstatusMessage;}
set{statusMessage=value;}
}
publicBooleanIsCompleted
{
get{returnisCompleted;}
set{isCompleted=value;}
}
}
4.2.这次我们使用的是一个windowsform的程序,完成的效果如下:
当我们创建一个工作流实例后,我们看到他的StatusMessage从Created-Ilded-Persisted-Unloaded变化,这是由于工 作流执行到ListenActivity中等待事件的时候,期状态会变成ilded,当ilded的时候工作流实例的状态信息将被持久化存 储到Sql数据中,状态从Persisted变成Unloaded,这个时候即使你关闭程序也没有关系,如果你点击继续按钮, StatusMessage的变化为Loaded-Ilded-Persisted-Unloaded,他会从新从数据库中装载被持久化的工作流,点击停止 后会变成Completed状态。
持久化后我们关闭应用程序在重写打开的时候会调用如下方法来加载所有的工作流实例,主要使用了GetAllWorkflows来获 所有工作流实例。
privatevoidRetrieveExistingWorkflows()
{
workflows.Clear();
foreach(SqlPersistenceWorkflowInstanceDescriptionworkflowDesc
in((SqlWorkflowPersistenceService)persistence).GetAllWorkflows())
{
Workflowworkflow=newWorkflow();
workflow.InstanceId=workflowDesc.WorkflowInstanceId;
workflow.StatusMessage="Unloaded";
workflows.Add(workflow.InstanceId,workflow);
}
if(workflows.Count>0)
{
RefreshData();
}
}
在宿主程序我们定义如下方法来加载SqlWorkflowPersistenceService和本地服务,SqlWorkflowPersistenceService
类的一些成员方法的使用差MSDN吧,
privatevoidAddServices(WorkflowRuntimeinstance)
{
//usethestandardSQLServerpersistenceservice
StringconnStringPersistence=String.Format("InitialCatalog={0};DataSource={1};IntegratedSecurity={2};","WorkflowPersistence",@"localhost\SQLEXPRESS","SSPI");
persistence=newSqlWorkflowPersistenceService(connStringPersistence,true,newTimeSpan(0,2,0),newTimeSpan(0,0,5));
instance.AddService(persistence);
//addtheexternaldataexchangeservicetotheruntime
ExternalDataExchangeServiceexchangeService=newExternalDataExchangeService();
instance.AddService(exchangeService);
//addourlocalservice
persistenceDemoService=newPersistenceDemoService();
exchangeService.AddService(persistenceDemoService);
}
其他的代码基本都是围绕着实现StatusMessage自动变化的,和工作流关系不大。
代码下载:PersistenceDemo
相关文章推荐
- 坚持学习WF(14):自定义持久化服务
- 坚持学习WF(14):自定义持久化服务
- 坚持学习WF(8):本地服务之调用外部方法
- 坚持学习WF(7):流程控制(Flow Control)
- 坚持学习WF(23):以代码的方式构造和执行RuleSet
- 坚持学习WF(18):使用IPendingWork接口
- 分布式服务框架-原理与实践:13---服务多版本-学习笔记
- WF工作流技术内幕 —— 通过Web服务调用Workflow工作流(开发持久化工作流)
- Android学习--13-服务
- 坚持学习WF(11):工作流通信与队列
- 坚持学习WF(6):开发可复用的宿主程序
- WF工作流与Web服务的相互调用 —— 通过Web服务调用Workflow工作流(开发持久化工作流)
- 坚持学习WF(22):跟踪规则
- 坚持学习WF(3):WF框架概览
- WF---常见服务:持久化跟踪
- 坚持学习WF(7):流程控制(Flow Control)
- 坚持学习WF(5):自定义活动(CustomActivity)
- 坚持学习WF(20):规则引擎中的活动条件
- 坚持学习WF(17):WF中的补偿
- 坚持学习WF(12):使用EventHandlingScopeActivity活动