Windows Workflow 作为 WCF 服务和工作流持久性






3.07/5 (8投票s)
工作流计算器 WCF 服务,一个长期运行工作流的示例
引言
Windows Workflow Foundation 是 .NET 3.0 和 3.5 的一项功能。在本文中,我将尝试解释如何将工作流公开 为 WCF Web 服务。
工作流的持久化也得到了详细解释。我以顺序计算器工作流服务为例。
背景
如果您是工作流新手,请参阅 MSDN 上的 此链接。它解释了所有工作流活动、持久化和 序列化概念。
Using the Code
上传的 zip 文件包含 4 个项目。该解决方案包含:
WorkFlowContracts
: 定义了一个ICalculator
服务合同。此合同会公开给客户端。WWFAsWCFService
: 这是一个实现ICalculator
合同的顺序计算器工作流。WorkflowService
: 公开上述工作流的服务。WinformClient
: 工作流服务的消费者。
要设置整个解决方案,您首先需要创建持久化数据库。为此,请使用 Microsoft 提供的持久化架构和逻辑脚本,位于以下位置:~\Windows\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\EN
在 SQL Server 中创建一个数据库,例如 PersistanceDB
。按顺序运行以下脚本:
- SqlPersistenceService_Schema.sql
- SqlPersistenceService_Logic.sql
完成此步骤后,您的持久化数据库即可用于工作流。
现在您需要设置持久化数据库的连接字符串。
打开工作流服务的 web.config 文件。在 Servicemodel
标签下,转到 ServiceBehaviour
并指定您的持久化数据库的连接。
<serviceBehaviors>
<behavior name="WorkFlowService.Service1Behavior">
<!-- To avoid disclosing metadata information,
set the value below to false and remove the metadata
endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
<workflowRuntime name="WorkflowServiceHostRuntime"
validateOnCreate="true" enablePerformanceCounters="true">
<services>
<add type="System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService,
System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35"
connectionString="Data Source=*******;
Initial Catalog=*******;user id=*******;
password=*******;Pooling=False"
LoadIntervalSeconds="1" UnLoadOnIdle= "true" />
</services>
</workflowRuntime>
</behavior>
</serviceBehaviors>
构建解决方案。运行 WorkflowService。确保 WinformClient
引用了工作流服务的正确 URL。这里的想法是,每次运行客户端时都使用同一个工作流实例。
当客户端首次运行时,通过调用 StartCalculator
方法创建工作流,如下所示。我将 workflowid
保存在 appsetting
中以供以后使用。
_calcChannel = new ChannelFactory<ICalculator>
("WSHttpContextBinding_ICalculator").CreateChannel();
_workFlowId = _calcChannel.StartCalculator();
Configuration config =
ConfigurationManager.OpenExeConfiguration(Application.ExecutablePath);
config.AppSettings.Settings.Remove(_WORKFLOWID);
config.AppSettings.Settings.Add(_WORKFLOWID, _workFlowId);
config.Save();
在工作流方面,整个工作流是使用一组 ReceiveActivities
设计的,每个活动实现 ICalculator
服务合同的 OperationContract
。
只有 StartCalculator
Receive 活动的 CreateInstance
设置为 true
,即只有一个 Receive
活动可以创建工作流实例。
一旦工作流被创建,您将在持久化数据库的 InstanceState
表中看到一个条目。
假设通过调用服务的 StartCalculator()
方法,您得到了工作流 ID。
174bf47b-4c8a-40d8-8432-0ac1f38eec9a
下次调用同一工作流实例时,将客户端按如下方式运行:
_calcChannel = new ChannelFactory<ICalculator>
("WSHttpContextBinding_ICalculator").CreateChannel();
IContextManager context =
(_calcChannel as IClientChannel).GetProperty<IContextManager>();
IDictionary<string, string> instanceIdContext =
new Dictionary<string, string>();
instanceIdContext.Add
("instanceId", "174bf47b-4c8a-40d8-8432-0ac1f38eec9a");
context.SetContext(instanceIdContext);
label1.Text = Convert.ToString(_calcChannel.AddNumbers(10, 20));
在上面的代码中,IContextManager
对象保存工作流的上下文信息。上下文无非就是使用 StartCalculator()
方法创建的 workflowid
。
通过创建一个以 instanceId
为键,以 174bf47b-4c8a-40d8-8432-0ac1f38eec9a
为值的字典,您可以重新实例化数据库中持久化的同一个工作流。应用上下文并调用计算器的 AddNumbers
方法。这对于长期运行的工作流非常有用。
关于 wsHttpContextBinding
为了与工作流服务通信,服务必须使用 basicHttpbinding
或 wsHttpBinding
。如果您想实现一些安全功能,例如上下文保护(签名、加密),则应使用 wsHttpContextBinding
。服务器端的 WorkflowServiceHost
(托管 WorkFlow
)使用此绑定与客户端通信。在我的示例中,我在 StartCalculator()
方法调用中返回 workflowid
。但是您也可以直接从通道获取上下文。如下所示。上下文仅在其中一个 Receive Activity(在我的情况下是 StartCalculator
receive activity)创建工作流实例时返回。
_calcChannel = new ChannelFactory<ICalculator>
("WSHttpContextBinding_ICalculator").CreateChannel();
_calcChannel.StartCalculator();
IContextManager context =
(_calcChannel as IClientChannel).GetProperty<IContextManager>();
IDictionary<string, string> instanceIdContext = context.GetContext();
希望本文能帮助您对工作流服务及其持久化有一个基本的了解。
关注点
我花了很长时间才弄清楚如何调用已持久化的工作流。IContextManager
是关键。通过应用上下文,您可以简单地调用同一个工作流实例。
现在您可以持久化工作流了。我建议您阅读有关持久化服务的内容,您可以在其中持久化服务本身的状态。
历史
- 2009年1月19日:初次发布