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();
}
結果
本文 例子下載:http://files.cnblogs.com/foundation/PersistenceSample.rar