系统盘\Windows\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\EN下 |
SqlPersistenceService_Schema.sql SqlPersistenceService_Logic.sql |
1.2 数据库时间格式说明
在SqlPersistenceService数据库中,时间值是GMT格式的, 这样做的目地是使用统一的时间轴, 如此可以解决一台在美国的服务器与一台在中国的服务器就可以协同工作时的时差问题 GMT比北京时间晚8小时 |
1.3 表结构
1.3.1 InstanceState
对这个表我以前有一个错误的习惯性叫法,叫它实例表,其实应叫未完成事例的运行状态表
uidInstanceID state status unlocked blocked info modified ownerID ownedUntil nextTimer |
1.3.2 CompletedScope
uidInstanceID completedScopeID state modified |
1.4 存储过程
2 SqlWorkflowPersistenceService
SqlWorkflowPersistenceService作为一个PersistenceService的功能实现类加载到WorkflowRuntime中为引擎提供了一种使用SQLServer数据实现持久化的功能。
SqlWorkflowPersistenceService类是使用SQL数据库对工作流状态进行持久化的服务
为了能够使用SqlWorkflowPersistenceService,数据库还需要启动DTC服务
2.1 加载说明
每当引擎起动时(StartRuntime),只要InstanceState表中有实例数据,就会将该实例载入引擎中,并将ownedUntil字段设为加载的时间
1. 引擎使用GetWorkflow方法,可通过SqlWorkflowPersistenceService服务将存于数据库中的实例加载并返回
2. 实例使用load方法,可触发引擎的WorkflowLoaded事件
3. 没有经过持久化的实例,调用load方法不会出错,也不产生引擎的WorkflowLoaded事件
4. 加载的持久化实例不用load方法也能直接操作,但这样不会产生引擎的WorkflowLoaded事件,调用load方法可以产生引擎的WorkflowLoaded事件,除此之外,我没跟出什么其他的
5. 引擎.GetWorkflow(GUID)方法可以返回一个引擎中存在的实例
如果引擎中不存在,SqlWorkflowPersistenceService服务会到数据库中找该实例,并将其加载到引擎
如果引擎中没有指定GUID的实例,会报Workflow with id "GUID" not found in state persistence store.
如没加载SqlWorkflowPersistenceService服务报的异常为The workflow hosting environment does not have a persistence service as required by an operation on the workflow instance
|
2.2 持久化说明
1. 当引擎停止时(StopRuntime),就会将引擎内的所有工作流实例存入InstanceState表,ownedUntil字段为空
注:没加载SqlWorkflowPersistenceService服务时, 引擎停止后,引擎并没有释放,引擎中的实例也存在,只是所有的执行都被系统级挂起, 当重新启动引擎时,所有的实例还可继续运行 |
2. 实例使用Unload方法,通过加载到引擎中的SqlWorkflowPersistenceService服务,完成实例的内存移出与保存到数据库的操作
3. 没有加载SqlWorkflowPersistenceService时,实例的TryUnload方法会报异常。
4. 如果调用UnLoad方法时,实例在挂起状态时(如:实例.Suspend)
status值为2 info值为Suspend方法的参数
unlocked值为1 blocked值为0 modified为操作的时间 nextTimer为9999-12-31 23:59:59.997 |
5. 如果调用UnLoad方法时,实例在引擎中创建后,还没开始执行前,
status值为4 info值为空 其他同上 |
1. 如果调用UnLoad方法时,实例在运行到Delay结点的idle状态
如调用Unload方法 status值为0 unlocked值为1 blocked值为1 nextTimer值为实际Delay应苏醒的时间。 |
2. 使用SqlWorkflowPersistenceService可以实现每当实例进入idle状态后,自动将调用Unload将其持久化
可以使用SqlWorkflowPersistenceService类的构造函数的unloadOnIdle参数设置是否自动持久化
3. DelayActivity的延时修正
DelayActivity是一个提供延时处理的组件,当实例处于Idle状态时,实例的UnloadOnIdle被置位。等时间到达后,该实例继续向下执行,
这里有一个问题,就是工作流实例被不同的进程进行处理时的延时修正问题
SqlWorkflowPersistenceService 提供了这个功能
InstanceState表的NextTime字段就是用于修正延时时间用的。
SqlWorkflowPersistenceService的构造函数中还有一个参数LoadingInterval,
此参数可以使引擎在多少时间间隔内去检测那些超时的工作流实例,如果超时了则自动进行加载并运行。
也就是引擎要过多久才去刷一次数据库,以查检是否有到时的实例
4. 重新加载工作流后,计时器不会恢复操作的错误
WF的一个BUG http://support.microsoft.com/kb/932394/zh-cn
|
2.4 锁定问题
工作流引擎加载工作流实例时,锁定该实例,这样其它引擎就不能加载这个工作流实例了。 当工作流实例保存回数据库后便解除锁定状态,这样其它引擎便可加载该工作流实例了。 当加载工作流实例的进程突然死掉,则数据库的锁定状态是不是永远都不能解锁了。 在SqlWorkflowPersistenceService的构造函数中有一个参数instanceOwnershipDuration,指明了锁定工作流实例的时间限制。 可以依据现实情况去估计一个工作流实例在某一个环节处理所用的时间进行设置,如10分钟。如果处理时间超过这个值则会被其它引擎自动解锁,也就是说解锁可以由其它引擎来进行而不依赖于当前的进程 实现过程: InstanceState表里记录着工作流的实例,OwnedUntil字段记录了该工作流实例锁定的到期时间,当引擎加载一个工作流实例时,它会将当前时间加上SqlWorkflowPersistenceService构造函数中的instanceOwnershipDuration参数指定的时间,并把相加的时间存放到OwnedUntil字段里。 数据库里有一个存储过程UnlockInstanceState,其它的工作流引擎就是用此存储过程来解锁被锁定的工作流实例。这个过程是引擎自动完成的.
|
2.5 构造函数说明
new SqlWorkflowPersistenceService(string connectionString)
|
参数:string connectionString 是持久化的数据库连接字串 |
new SqlWorkflowPersistenceService(string connectionString, bool unloadOnIdle, TimeSpan instanceOwnershipDuration , TimeSpan loadingInterval) |
参数:string connectionString 是持久化的数据库 参数:bool unloadOnIdle 为真表示自动将调用Unload将Delay状态的实例持久化 参数:TimeSpan instanceOwnershipDuration 引擎锁定实例,防止其他引擎加载的时间 参数:TimeSpan loadingInterval 是引擎自动到数据库中查找是否有idle到实例的时间步长 |
2.6 属性
EnableRetries属性 |
|
LoadingInterval属性 |
Gets the length of the loading interval. |
ServiceInstanceId属性 |
Gets the service instance identifier. |
2.7 GetAllWorkflows()方法
Retrieves instance descriptions of all persisted workflows.
得到所有被持久化的实例说明,
1. 当实例被持久化后,实例信息从引擎列表中移出,会添加到持久化列表中
2. 当引擎启动后,会从持久化数据库中加载所有被持久化的数据,这时引擎列表与该列表内容相同
3. 当实例完成后,实例信息从引擎列表中移出,也从持久化列表中移出
SqlWorkflowPersistenceService SWPS=new SqlWorkflowPersistenceService("constring"); System.Collections.IEnumerable workflows = SWPS.GetAllWorkflows(); foreach (SqlPersistenceWorkflowInstanceDescription instanceDescription in workflows) { string v=instanceDescription.SuspendOrTerminateDescription; Guid guid =instanceDescription.WorkflowInstanceId; bool b = instanceDescription.IsBlocked; DateTime time = instanceDescription.NextTimerExpiration.Value; WorkflowStatus st = instanceDescription.Status; //WorkflowStatus.Completed //WorkflowStatus.Created //WorkflowStatus.Running //WorkflowStatus.Suspended //WorkflowStatus.Terminated } |
2.8 LoadExpiredTimerWorkflowIds()方法
Retrieves a list of completed timer instances.As IList(Of Guid)
SqlWorkflowPersistenceService SWPS=new SqlWorkflowPersistenceService("constring");
foreach (Guid guid in SWPS.LoadExpiredTimerWorkflowIds()) { string v = guid.ToString(); } |
3 实例与持久化相关的方法
Load |
加载实例 加载的持久化实例不用load方法也能直接操作, 但这样不会产生引擎的WorkflowLoaded事件, 调用load方法可以产生引擎的WorkflowLoaded事件, 除此之外,我没跟出什么其他的 |
TryUnload |
从内存中卸载实例,返回Boolean
如果实例处于idle或suspended状态,
TryUnload用 persistence服务将实例从内容中移除,并将该实例持久化到数据库中,
如果没有persistence服务加载到引擎,TryUnload 方法会产生一个 InvalidOperationException. 异常。
如果实例被成功的持久化, 引擎将触发 WorkflowUnloaded事件并返回true.
如果实例已经unloaded,terminated,aborted,completed,则返回false
将实例从内存中移出可以释放系统资源 |
Unload |
Unload 是同步的.其他同上
|
4 引擎引持久化相关的事件
WorkflowUnloaded |
|
WorkflowLoaded |
|
|
|
|
|
|
|