WF4.0 基础篇 (十九) Persistence 持久化
本节主要介绍WF4 中持久化的使用
本文例子下载:
https://files.cnblogs.com/foundation/PersistenceSample.rar
Persistence 持久化
WF4提供了一个抽象类System.Runtime.Persistence.InstanceStore,用于定义持久化的实现.该类来自于System.Runtime.dll
可以从InstanceStore类继承来开发Persistence Provider,持久化过程中的对实例的数据访问需要另外一个继承自System.Activities.Persistence.PersistenceParticipant
WF4提供了一个基于SQL Server的持久化类SqlWorkflowInstanceStore
持久化的所有者
当只对实例进行持久化([实例.PersistableIdle = PersistableIdleAction.Persist] 或instance.Persist(),或Persist Activity),而没将实例时UnLoad时,该持久化的实例被其所有者锁定.如果对Load持久化的实例不是该实例的所有者,会报如下异常:
The execution of an InstancePersistenceCommand was interrupted because the instance 'c42a0d7d-d652-404a-9734-67acb163ea48' is locked by a different instance owner. This error usually occurs because a different host has the instance loaded. The instance owner ID of the owner or host with a lock on the instance is 'c9959a30-60aa-47ae-a119-bc8ff1b97720'. |
因为实例"c42a0d7d-d652-404a-9734-67acb163ea48"一个不同的实例的所有者被锁定,被打断了一个 InstancePersistenceCommand 的执行。因为不同的主机有实例加载时,通常会发生此错误。实例的拥有人或主机实例上的锁的所有者 ID 是 ' c9959a30-60aa-47ae-a119-bc8ff1b97720。 |
关于Activity.CacheMetadata方法
注意:Activity.CacheMetadata方法会多次被调用
流程中的Activity.CacheMetadata方法会在Run时全部调用,
每当从持久化中Load实例时,Activity.CacheMetadata方法会再次全部调用
与持久化相关的事件执行顺序
实例.PersistableIdle
实例.Idle
实例.Unloaded
当实例完成后,执行完[实例.Completed]后才执行[实例.Unloaded]
SqlWorkflowInstanceStore
数据库
\Windows\Microsoft.NET\Framework\v4.0.21006\SQL\en |
SqlWorkflowInstanceStoreSchema.sql SqlWorkflowInstanceStoreLogic.sql |
SqlWorkflowInstanceStore 类
类名 | System.Activities.DurableInstancing.SqlWorkflowInstanceStore |
文件 | System.Activities.DurableInstancing.dll System.Runtime.dll |
结构说明 | 继承 InstanceStore 是一个 sealed类 override 了 [BeginTryCommand方法] 与 [EndTryCommand方法]与 [OnFreeInstanceHandle方法]与 [OnNewInstanceHandle方法] [ConnectionString]属性 的类型为[string] [EnqueueRunCommands]属性 的类型为[bool] [HostLockRenewalPeriod]属性 的类型为[TimeSpan] [InstanceCompletionAction]属性 的类型为[InstanceCompletionAction] [InstanceEncodingOption]属性 的类型为[InstanceEncodingOption] [InstanceLockedExceptionAction]属性 的类型为[InstanceLockedExceptionAction] 无返回值[Promote]方法,(string name, IEnumerable<XName> promoteAsVariant, IEnumerable<XName> promoteAsBinary) |
功能说明 | [ConnectionString]属性 ,数据库字串
[EnqueueRunCommands]属性,
[HostLockRenewalPeriod]属性,服务宿主在指定时间内必须更新锁定时间周期
[InstanceCompletionAction]属性,实例完成后是否删除持久化存储中的数据,DeleteAll(默认),DeleteNothing
[InstanceEncodingOption]属性,保存到持久化存储的压缩算法,None(默认),GZip,
[InstanceLockedExceptionAction]属性,当发生InstanceLockedException异常时(该异常发生在当他要去锁定已经被其他服务宿主锁定的实例时)的操作NoRetry(默认),BasicRetry,AggressiveRetry
[Promote]方法 |
PersistableIdleAction.Unload方式持久化
要将实例持久化,有很多种方式可以使用,其中一种就是使用[实例.PersistableIdle 回调函数],它在实例Idle时触发。
当 [实例.PersistableIdle = e => PersistableIdleAction.Persist],实例被持久化,但并没有被UnLoad,这时Load时要主意持久化的所有者
当 [实例.PersistableIdle = e => PersistableIdleAction.UnLoad],实例被持久化,然后被UnLoad,这时Load时不用考虑所有者
//===================================================
WorkflowApplication instance = null;
void workflowCompleted(WorkflowApplicationCompletedEventArgs e) { instance = null; System.Console.WriteLine("workflowCompleted:{0}", e.CompletionState.ToString()); }
void workflowIdel(WorkflowApplicationIdleEventArgs e) {
System.Console.WriteLine("Idle:{0}", e.InstanceId); }
void unload(WorkflowApplicationEventArgs e) { System.Console.WriteLine("unload:{0}", e.InstanceId); } PersistableIdleAction persistableIdle(WorkflowApplicationIdleEventArgs e) {
System.Console.WriteLine("persistableIdle:{0}", e.InstanceId);
return PersistableIdleAction.Unload; } //==================================================
void triggering() { string bookName = textBox_bookmark.Text; string inputValue = textBox_value.Text;
if (instance != null) { if (instance.GetBookmarks().Count(p => p.BookmarkName == bookName) == 1) { instance.ResumeBookmark(bookName, inputValue); } } }
void create() { instance = new WorkflowApplication(new FlowcharLibrary.FlowDecisionWorkflow());
// string connectionString = "Data Source=.;Initial Catalog=WorkflowInstanceStore;Integrated Security=True"; SqlWorkflowInstanceStore instanceStore = new SqlWorkflowInstanceStore(connectionString);
instance.InstanceStore = instanceStore;
instance.PersistableIdle = persistableIdle;
instance.Idle = workflowIdel;
instance.Unloaded = unload;
instance.Completed = workflowCompleted;
textBox_Guid.Text = instance.Id.ToString(); instance.Run(); }
void load() { instance = new WorkflowApplication(new FlowcharLibrary.FlowDecisionWorkflow());
// string connectionString = "Data Source=.;Initial Catalog=WorkflowInstanceStore;Integrated Security=True"; SqlWorkflowInstanceStore instanceStore = new SqlWorkflowInstanceStore(connectionString);
instance.InstanceStore = instanceStore; instance.PersistableIdle = persistableIdle;
instance.Completed = workflowCompleted; instance.Unloaded = unload; instance.Idle = workflowIdel;
Guid guid = new Guid(textBox_Guid.Text);
instance.Load(guid);
}
|
手动方式持久化
可以不使用[实例.PersistableIdle = e => PersistableIdleAction.UnLoad]的方式持久化实例而使用
[实例.Persist方法] 与 [实例.Unload方法] 方式,
[实例.Unload方法]会触发[实例.Unload事件]
void unload() { instance.Persist(); instance.Unload(); } |
InstanceView
类名 | System.Runtime.Persistence.InstanceView |
文件 | System.Runtime.dll |
结构说明 | 继承 Object 是一个 sealed类
[InstanceData]属性 的类型为[ IDictionary<XName, InstanceValue>] [InstanceDataConsistency]属性 的类型为[InstanceValueConsistency] [InstanceId]属性 的类型为[Guid] [InstanceKeys]属性 的类型为[ IDictionary<Guid, InstanceKeyView>] [InstanceKeysConsistency]属性 的类型为[ InstanceValueConsistency] [InstanceMetadata]属性 的类型为[ IDictionary<XName, InstanceValue>] [InstanceMetadataConsistency]属性 的类型为[ InstanceValueConsistency ] [InstanceOwner]属性 的类型为[ InstanceOwner] [InstanceOwnerMetadata]属性 的类型为[IDictionary<XName, InstanceValue>] [InstanceOwnerMetadataConsistency]属性 的类型为[InstanceValueConsistency] [InstanceState]属性 的类型为[InstanceState] [InstanceStoreQueryResults]属性 的类型为[ReadOnlyCollection<InstanceStoreQueryResult>] [IsBoundToInstance]属性 的类型为[bool] [IsBoundToInstanceOwner]属性 的类型为[bool] [IsBoundToLock]属性 的类型为[bool] |
功能说明 |
基本使用
//===================================================
WorkflowApplication instance = null;
SqlWorkflowInstanceStore instanceStore;
InstanceView view;
void workflowCompleted(WorkflowApplicationCompletedEventArgs e) { instance = null; System.Console.WriteLine("workflowCompleted:{0}", e.CompletionState.ToString()); }
void workflowIdel(WorkflowApplicationIdleEventArgs e) {
System.Console.WriteLine("Idle:{0}", e.InstanceId); }
void unload(WorkflowApplicationEventArgs e) { System.Console.WriteLine("unload:{0}", e.InstanceId); }
PersistableIdleAction persistableIdle(WorkflowApplicationIdleEventArgs e) {
System.Console.WriteLine("persistableIdle:{0}", e.InstanceId);
return PersistableIdleAction.Unload; } //==================================================
void create() { instance = new WorkflowApplication(new FlowcharLibrary.FlowDecisionWorkflow());
// if (instanceStore == null) { string connectionString = "Data Source=.;Initial Catalog=WorkflowInstanceStore;Integrated Security=True"; instanceStore = new SqlWorkflowInstanceStore(connectionString); view = instanceStore.Execute(instanceStore.CreateInstanceHandle(), new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(30)); instanceStore.DefaultInstanceOwner = view.InstanceOwner; }
instance.InstanceStore = instanceStore;
instance.PersistableIdle = persistableIdle;
instance.Idle = workflowIdel;
instance.Unloaded = unload;
instance.Completed = workflowCompleted;
textBox_Guid.Text = instance.Id.ToString(); instance.Run(); }
void load() { instance = new WorkflowApplication(new FlowcharLibrary.FlowDecisionWorkflow());
if (instanceStore == null) { string connectionString = "Data Source=.;Initial Catalog=WorkflowInstanceStore;Integrated Security=True"; instanceStore = new SqlWorkflowInstanceStore(connectionString); view = instanceStore.Execute(instanceStore.CreateInstanceHandle(), new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(30));
instanceStore.DefaultInstanceOwner = view.InstanceOwner; }
instance.InstanceStore = instanceStore;
instance.PersistableIdle = persistableIdle;
instance.Idle = workflowIdel;
instance.Unloaded = unload;
instance.Completed = workflowCompleted;
Guid guid = new Guid(textBox_Guid.Text);
instance.Load(guid);
}
void triggering() { string bookName = textBox_bookmark.Text; string inputValue = textBox_value.Text;
if (instance != null) { if (instance.GetBookmarks().Count(p => p.BookmarkName == bookName) == 1) { instance.ResumeBookmark(bookName, inputValue); } } } |
Persist Activity 方式持久化
使用Persist Activity,可以在其出现的位置使实例持久化,不管实例是否处于Idle状态.
类名 | System.Activities.Statements.Persist |
文件 | System.Activities.dll |
结构说明 | 继承 NativeActivity 是一个 sealed类 override 了 [CacheMetadata方法] 与 [Execute方法] |
功能说明 | [Persist] 可以触发[Idel] |
例:基本使用
工作流 | |
宿主 | WorkflowApplication instance = null;
SqlWorkflowInstanceStore instanceStore;
InstanceView view;
void workflowCompleted(WorkflowApplicationCompletedEventArgs e) { instance = null; System.Console.WriteLine("workflowCompleted:{0}", e.CompletionState.ToString()); }
void workflowIdel(WorkflowApplicationIdleEventArgs e) {
System.Console.WriteLine("Idle:{0}", e.InstanceId); }
void unload(WorkflowApplicationEventArgs e) { System.Console.WriteLine("unload:{0}", e.InstanceId); }
//==================================================
private void button_PersistWorkflow_Click(object sender, RoutedEventArgs e) { instance = new WorkflowApplication(new PersistenceWindow.PersistWorkflow());
// if (instanceStore == null) { string connectionString = "Data Source=.;Initial Catalog=WorkflowInstanceStore;Integrated Security=True"; instanceStore = new SqlWorkflowInstanceStore(connectionString); view = instanceStore.Execute(instanceStore.CreateInstanceHandle(), new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(30)); instanceStore.DefaultInstanceOwner = view.InstanceOwner; }
instance.InstanceStore = instanceStore;
instance.Idle = workflowIdel;
instance.Unloaded = unload;
instance.Completed = workflowCompleted;
textBox_Guid.Text = instance.Id.ToString(); instance.Run(); } |
结果 |