工作流(WF)中使用SqlWorkflowPersistenceService创建完全的持久性服务

时间:2021-12-13 10:10:54

SqlWorkflowPersistenceService 类表示功能完全的持久性服务。 您可以使用这一现成可用的服务,在工作流运行时引擎请求工作流实例时,保留和检索有关该工作流实例的工作流状态信息。

SqlWorkflowPersistenceService 服务会参与 WorkflowCommitWorkBatchService 所提供的工作流事务批处理功能。 也就是说,它会将表示 SQL 数据库挂起写入的对象添加到当前批次并实现 IPendingWork 接口。

现成可用的 SqlWorkflowPersistenceService 类实现可实现锁定对其数据库中工作流状态信息的访问(用于其他进程中运行的持久性服务可能有权访问单个数据存储区的环境下)。 Sql 数据库架构中的一个列用于将特定工作流运行时所用的工作流实例标记为锁定。 在非活动状态持续了预定义的一段时间后,工作流运行时会释放这些锁定。 此非活动的时间期限是在 SqlWorkflowPersistenceService 类的构造函数中定义的。 提供此功能是为了处理以下情况:工作流运行时所访问的工作流实例已由其他工作流运行时加载。 尝试加载该工作流的第二个运行时将获得 WorkflowOwnershipException。

如果使用的 SqlWorkflowPersistenceService 的构造函数没有为 instanceOwnershipDuration 提供参数,将不实现锁定。 如果为此参数提供了任意值(即使是 TimeSpan.MaxValue),将会启用锁定。

有关一般锁定和持久性服务的更多信息,请参见 Windows 工作流持久性服务。

SqlWorkflowPersistenceService 管理的另一种工作流状态是计时器时间跨度。 此信息是在工作流定义之内使用 DelayActivity 活动配置的。 SqlWorkflowPersistenceService 首次加载某个工作流时,其所有计时器配置都会注册到工作流运行时中。 通过使用 SqlWorkflowPersistenceService 中定义的 LoadingInterval 属性,可以检查工作流实例,以确定每个工作流实例上是否有需要处理的任何时间事件。

如果在工作流应用程序中同时使用 SqlTrackingService 和 SqlWorkflowPersistenceService,建议为持久性和跟踪使用单一数据库。

为 Microsoft 分布式事务协调器打开 TCP 端口 135

使用 SqlWorkflowPersistenceService 服务将工作流持久保留到远程 SQL Server 之前,必须确保 Windows 防火墙已为 Microsoft 分布式事务中心 (MSDTC) 打开 TCP 端口 135。 为此,请按下列步骤操作:

使用 Windows 防火墙打开 TCP 端口 135

单击“开始”,然后单击“控制面板”。

打开“Windows 防火墙”。

单击“异常”选项卡。

单击“添加程序”。

在“浏览”对话框中,输入 \WINDOWS\system32\msdtc.exe

单击“打开”,然后单击“确定”。

单击“添加端口”。

输入这个打开端口的名称,然后在“端口号”字段中输入 135。

选择“TCP”,然后单击“确定”。

创建 SQL 持久性数据库

Windows Workflow Foundation 安装程序并不安装 SqlWorkflowPersistenceService 服务所需的数据库,但会安装为这些服务创建和配置数据库所用的 SQL 脚本。 本部分详细说明正确配置供 SqlWorkflowPersistenceService 服务使用的 SQL Server 数据库所需执行的步骤。

由 Windows Workflow Foundation 安装的 SQL 服务使用 SQL Server 来存储信息。 对于这些任务,可以使用 Microsoft SQL Server 2005 Express、SQL Server 2000 或更高版本或 SQL Server 2000 Desktop Engine (MSDE)。

创建 SQL 持久性数据库

在 SQL Server 2005 Express、SQL Server 2000 或更高版本或 SQL Server 2000 Desktop Engine (MSDE) 中,使用以下 SQL 查询语句创建一个名为 WorkflowPersistenceStore 的新数据库:

CREATE DATABASE WorkflowPersistenceStore

在 SQL 查询分析器工作区中,从可用数据库列表中选择在步骤 1 中创建的数据库。

在“文件”菜单上,单击“打开”,然后打开 SQL 脚本 %WINDIR%\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\<语言>\SqlPersistence_Schema

通过单击“执行”或按 F5 来运行查询,以便创建 SQL 持久性服务表。

在“文件”菜单上,单击“打开”,然后打开 SQL 脚本 %WINDIR%\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\<语言>\SqlPersistence_Logic

通过单击“执行”或按 F5 来运行查询,以便创建 SQL 持久性服务存储过程。

向运行时引擎添加 SqlWorkflowPersistenceService

可以编程方式或通过使用应用程序配置文件,向 Windows Workflow Foundation 运行时引擎添加运行时服务。

修改 SqlWorkflowPersistenceService 的 app.config

在 app.config 文件的 Services 元素中,创建一个名为 add 的新元素。

add 元素添加名为 type 的属性,该属性的值为 System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35。

add 元素添加名为 connectionString 的属性,该属性的值为 Initial Catalog=WorkflowPersistenceStore;Data Source=localhost;Integrated Security=SSPI。

可能需要修改连接字符串,具体取决于 SQL Server 的配置。 此处显示的连接字符串假定,数据库名称为 WorkflowPersistenceStore,且 SQL Server 已安装在用于应用程序开发的同一个系统上。

通过添加与 SqlWorkflowPersistenceService 类中定义的可配置属性 (property) 相对应的属性 (attribute),对 SqlWorkflowPersistenceService 服务进行配置。

例如,若要指定应在工作流进入空闲状态时将其卸载(例如在使用了 DelayActivity 活动的情况下),请向 add 元素添加名为 UnloadOnIdle 的属性,并为该属性指定 true 值。

<add type="System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionString="Initial Catalog=WorkflowPersistenceStore;Data Source=localhost;Integrated Security=SSPI;" UnloadOnIdle="true"/>

以编程方式向运行时引擎添加 SqlWorkflowPersistenceService

调用 WorkflowRuntime 类中定义的 AddService 方法,传递 SqlWorkflowPersistenceService 的新实例。

下面的示例演示如何使用与前面的过程中显示的示例相同的配置来创建 SqlWorkflowPersistenceService 服务。 在此示例中,instanceOwnershipDuration 设置为 TimeSpan.MaxValue,而 loadingInterval 设置为 2 分钟。 这些值是在 SqlWorkflowPersistenceService 类中使用的默认值。

[C#]

using (WorkflowRuntime workflowRuntime = new WorkflowRuntime()) {

// Create the SqlWorkflowPersistenceService.

string connectionString = ="Initial Catalog=WorkflowPersistenceStore;Da

ta Source=localhost;Integrated Security=SSPI;"
bool unloadOnIdle = true;
TimeSpan instanceOwnershipDuration = TimeSpan.MaxValue;
TimeSpan loadingInterval = new TimeSpan(0, 2, 0);
SqlWorkflowPersistenceService persistService = new SqlWorkflowPersistenceService(connectionString, unloadOnIdle, instanceOwnershipDuration, loadingInterval); // Add the SqlWorkflowPersistenceService to the runtime engine.
workflowRuntime.AddService( persistService );
// ...
}