博客园  :: 首页  :: 联系 :: 订阅 订阅  :: 管理

[译]Windows Workflow Foundation 4 和持久性

Posted on 2009-11-20 20:05  生鱼片  阅读(3735)  评论(3编辑  收藏  举报

原文地址:http://msmvps.com/blogs/theproblemsolver/archive/2009/11/19/windows-workflow-foundation-4-and-persistence.aspx
 

WF4中的持久化模型有了很大的变化。 

SqlWorkflowInstanceStoreWF提供给我们的开箱即用的类,它会将工作流数据保存到SQL Server 2005或是2008中。该类从InstanceStore类继承,
如果你要实现自己的持久性功能就需要实现该类的子类。
 

我们可以用SqlWorkflowInstanceStore来做什么?

我们可以将它附加到一个WorkflowApplication或一个WorkflowServiceHost上,在我们需要的时候来持久化工作流。注意WorkflowInvoker是不支持持久化的。 

下面是在WorkflowApplication中使用的例子:

var instanceStore = new SqlWorkflowInstanceStore(connStr);

WorkflowApplication app = new WorkflowApplication(workflow);

app.InstanceStore = instanceStore;

app.Run();
 

首先你需要存储工作流状态的数据库,在

C:\Windows\Microsoft.NET\Framework\v4.0.21006\SQL\en”文件夹下有一些SQL文件,SqlWorkflowInstanceStoreSchema.sql SqlWorkflowInstanceStoreLogic.sql持久化需要的,可以创建了一个批处理文件来快速重新创建数据库,如下:

osql -E -S .\sqlexpress -Q "Drop Database WorkflowInstanceStore"

osql -E -S .\sqlexpress -Q "Create Database WorkflowInstanceStore"

osql -E -S .\sqlexpress -d WorkflowInstanceStore -i SqlWorkflowInstanceStoreSchema.sql

osql -E -S .\sqlexpress -d WorkflowInstanceStore -i SqlWorkflowInstanceStoreLogic.sql


我们需要告诉
WorkflowApplication什么时候持久化工作流,有很多种方式可以使用,其中一种就是使用PersistableIdle回调函数,它在工作流Idle并且允许持久化时激发。我们可以持久化并卸载工作流,也可以只卸载工作流。如下:
app.PersistableIdle = e => PersistableIdleAction.Persist; 

还有一种方式就是使用Persist活动,他可以允许在其他的持久化点来持久化工作流,不管工作流是否处于Idle状态。 

WorkflowServiceHost中如何使用?

WorkflowServiceHost中使用有一些不同,首先创建一个SqlWorkflowInstanceStore 实例,并设置如下:

var workflow = new Workflow1();

var baseAddress = new Uri("http://localhost:8080/MyWorkflow");

var host = new WorkflowServiceHost(workflow, baseAddress);

 

var connStr = @"Data Source=.\sqlexpress;Initial Catalog=WorkflowInstanceStore;Integrated Security=True;Pooling=False";

var instanceStore = new SqlWorkflowInstanceStore(connStr);

host.DurableInstancingOptions.InstanceStore = instanceStore;  

host.Open();  

Console.WriteLine("Listening...");

Console.ReadLine();

host.Close();

 

代码很简单,但是当工作流持久化时我们不能做任何的控制,能做的仅仅是使用WorkflowIdleBehavior来设置一些timeout的值如下:

var workflowIdleBehavior = new WorkflowIdleBehavior();

workflowIdleBehavior.TimeToPersist = TimeSpan.FromSeconds(10);

workflowIdleBehavior.TimeToUnload = TimeSpan.FromMinutes(1);

host.Description.Behaviors.Add(workflowIdleBehavior);
 

如果我们想要通过一些方式对SqlWorkflowInstanceStore行为进行更多的控制。我们可以使用SqlWorkflowInstanceStoreBehavior。下面使用类的方式也可以通过配置文件完成:

var connStr = @"Data Source=.\sqlexpress;Initial Catalog=WorkflowInstanceStore;Integrated Security=True;Pooling=False";

var behavior = new SqlWorkflowInstanceStoreBehavior(connStr);

behavior.InstanceCompletionAction = InstanceCompletionAction.DeleteNothing;

behavior.InstanceLockedExceptionAction = InstanceLockedExceptionAction.AggressiveRetry;

behavior.InstanceEncodingOption = InstanceEncodingOption.None;

host.Description.Behaviors.Add(behavior);
 

当多个 WorkflowApplication 实例中使用相同的 SqlWorkflowInstanceStore时会有一些复杂。不过在WorkflowServiceHost中会自动负责处理这种情况。
 

默认情况下一个SqlWorkflowInstanceStore 将只使用一个单一的 WorkflowApplication。如果您尝试与多个工作流使用,你会得到一个InstancePersistenceCommandException 异常,如下:

SqlWorkflowInstanceStore does not support creating more than one lock owner concurrently. Consider setting InstanceStore.DefaultInstanceOwner to share the store among many applications.
 

从上面的信息可以看出,技巧就是要设置SqlWorkflowInstanceStore

DefaultInstanceOwner属性,如下:

var instanceStore = new SqlWorkflowInstanceStore(connStr);

 

var instanceHandle = instanceStore.CreateInstanceHandle();

var createOwnerCmd = new CreateWorkflowOwnerCommand();

var view = instanceStore.Execute(instanceHandle, createOwnerCmd, TimeSpan.FromSeconds(30));

instanceStore.DefaultInstanceOwner = view.InstanceOwner;

 

// Do whatever needs to be dome with multiple WorkflowApplications

var deleteOwnerCmd = new DeleteWorkflowOwnerCommand();

instanceStore.Execute(instanceHandle, deleteOwnerCmd, TimeSpan.FromSeconds(30));
 

关键是要在开始时执行所需的CreateWorkflowOwnerCommand,当您使用 CreateWorkflowOwnerCommand 时要确保不能忘记最后执行

DeleteWorkflowOwnerCommand ,否则所有工作流让然还被所有者锁定,不能重新加载另一个 SqlWorkflowInstanceStore 

可以看出,WF4中的持久性比以前更灵活。 

译者注:

1.       Beta2中使用SqlWorkflowInstanceStore InstanceStore 取代了Beta1中的

SqlPersistenceProviderFactory PersistenceProviderFactory

2. PersistableIdleAction枚举有三个值:NoneUnloadPersist