这篇我来为asp.net中的报销多级审批工作流项目加上跟踪服务。
SqlTrackingService 服务还会在其数据库中保留跟踪配置文件。 工作流运行时引擎知道对所使用的任何跟踪配置文件所做的更改。 SqlTrackingService 服务实现
第一:配置跟踪用的数据库。
在C:\WINDOWS\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\EN目录下有两个文件Tracking_Schema.sql和Tracking_Logic.sql,安先后顺序执行。
第二:配置跟踪服务。配置文件如下:
<configuration>
<configSections>
<section name="WorkflowWithTracking"
type="System.Workflow.Runtime.Configuration.WorkflowRuntimeSection, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</configSections>
<WorkflowWithTracking>
<CommonParameters>
<add name="ConnectionString"
value="Data Source=.;Initial Catalog=c6ps;Integrated Security=True"/>
</CommonParameters>
<Services>
<add type="System.Workflow.Runtime.Tracking.SqlTrackingService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
</Services>
</WorkflowWithTracking>
</configuration>
第三:修改封装的WorkflowWrapper类,在实例化WorkflowRuntime时加入跟踪服务。
_SqlTrackingService = new SqlTrackingService(ConfigurationManager.ConnectionStrings["perstr"].ConnectionString);
if (runtime.GetService(_SqlTrackingService.GetType()) == null)
{
//加入跟踪服务
runtime.AddService(_SqlTrackingService);
}
说明:这个调用代码要在整个工作流的最后调用,否则跟踪不到任何信息,在本项目中就是财务审批的地方,如果放在员工提交审批的地方是不能调出任何信息的。
下面是页面输出的信息:
Workflow Events Date: 2009-3-1 9:10:43,
Status: Created Date: 2009-3-1 9:10:43,
Status: Started Date: 2009-3-1 9:10:57,
Status: Unloaded Date: 2009-3-1 9:10:57,
Status: Persisted Date: 2009-3-1 9:13:40,
Status: Loaded Date: 2009-3-1 9:13:40,
Status: Idle Date: 2009-3-1 9:13:40,
Status: Unloaded Date: 2009-3-1 9:13:40,
Status: Persisted Date: 2009-3-1 10:31:43,
Status: Loaded Date: 2009-3-1 10:31:43,
Status: Unloaded Date: 2009-3-1 10:31:43,
Status: Persisted Date: 2009-3-1 10:31:45,
Status: Loaded Date: 2009-3-1 10:31:45,
Status: Idle Date: 2009-3-1 10:31:45,
Status: Unloaded Date: 2009-3-1 10:31:45,
Status: Persisted Activity Events Activity: Workflow1 Date: 2009-3-1 9:10:43
Status: Executing Activity: whileActivity1 Date: 2009-3-1 9:13:40
Status: Executing Activity: sequenceActivity1 Date: 2009-3-1 9:13:40
Status: Executing Activity: listenActivity1 Date: 2009-3-1 9:13:40
Status: Executing Activity: eventDrivenActivity1 Date: 2009-3-1 9:13:40
Status: Executing Activity: OnStaffSubmit Date: 2009-3-1 9:13:40
Status: Executing Activity: OnStaffSubmit Date: 2009-3-1 9:13:40
Status: Closed Activity: eventDrivenActivity1 Date: 2009-3-1 9:13:40
Status: Closed Activity: listenActivity1 Date: 2009-3-1 9:13:40
Status: Closed Activity: sequenceActivity1 Date: 2009-3-1 9:13:40
Status: Closed Activity: sequenceActivity1 Date: 2009-3-1 9:13:40
Status: Executing Activity: listenActivity1 Date: 2009-3-1 9:13:40
Status: Executing Activity: eventDrivenActivity3 Date: 2009-3-1 10:31:43
Status: Executing Activity: OnPMSubmitMin Date: 2009-3-1 10:31:45
Status: Executing Activity: OnPMSubmitMin Date: 2009-3-1 10:31:45
Status: Closed Activity: eventDrivenActivity3 Date: 2009-3-1 10:31:45
Status: Closed Activity: listenActivity1 Date: 2009-3-1 10:31:45
Status: Closed Activity: sequenceActivity1 Date: 2009-3-1 10:31:45
Status: Closed Activity: sequenceActivity1 Date: 2009-3-1 10:31:45
Status: Executing Activity: listenActivity1 Date: 2009-3-1 10:31:45
Status: Executing
注意:跟踪服务是和数据库打交道的,我们需要清楚它的系统开销,这里为了简单我们创建一个控制台的工作流,工作流中拉入一个codeActivity,执行代码为:
{
Console.WriteLine("codeActivity1执行了!");
}
客户端程序代码为:
private static String strConn = "";
static void Main(string[] args)
{
WorkflowRuntimeSection config;
config = ConfigurationManager.GetSection("WorkflowWithTracking") as WorkflowRuntimeSection;
//数据库连接串
strConn = config.CommonParameters["ConnectionString"].Value;
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime("WorkflowWithTracking"))
{
SqlTrackingService sts = new SqlTrackingService(strConn);
AutoResetEvent waitHandle = new AutoResetEvent(false);
workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); };
if (workflowRuntime.GetService(sts.GetType()) == null)
{
//加入跟踪服务
workflowRuntime.AddService(sts);
}
WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(ApproveWorkFlow.WorkflowConsole.Workflow1));
instance.Start();
waitHandle.WaitOne();
Console.WriteLine("---DumpTrackingEvents开始---");
DumpTrackingEvents(instance.InstanceId);
Console.WriteLine("---DumpTrackingEvents结束---");
Console.Read();
}
}
下面是数据库的跟踪图:从图中的红圈中可以看到有六次sp_reset_connection,它的定义是存储过程由 SQL Server 用来支持事务中的远程存储过程调用。SqlConnection.Open一次,就调用sp_reset_connection来重新整理连接中的属性和变量。可以看出一次跟踪对数据库的开销还是挺大的,这在实际应用中应该要考虑清楚。
如果在工作流应用程序中同时使用 SqlTrackingService 和 SqlWorkflowPersistenceService,建议为持久性和跟踪使用单一数据库。运行时引擎启动后,如果没有添加其他 WorkflowCommitWorkBatch 服务,则 WorkflowRuntime 类将创建 DefaultWorkflowCommitWorkBatchService 对象。 可以在工作流中使用此服务以支持数据完整性所需的工作批次。 也可以选择使用SharedConnectionWorkflowCommitWorkBatchService 服务。 此服务用于在不同对象之间使用共享连接的数据库事务。 若要在 WorkflowRuntime 实例中使用 SharedConnectionWorkflowCommitWorkBatchService 服务而不是 DefaultWorkflowCommitWorkBatchService 服务,请使用 AddService 方法。[MSDN]
配置节点:
<configuration>
<configSections>
<section name="WorkflowWithTracking"
type="System.Workflow.Runtime.Configuration.WorkflowRuntimeSection, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</configSections>
<WorkflowWithTracking>
<CommonParameters>
<add name="ConnectionString"
value="data source=.;database=SqlPersistenceService;persist security info=False;user id=sa;pwd=sa; packet size=4096;"/>
</CommonParameters>
<Services>
<add type="System.Workflow.Runtime.Tracking.SqlTrackingService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
<add type="System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
UnloadOnIdle="true" />
<add type= "System.Workflow.Runtime.Hosting.SharedConnectionWorkflowCommitWorkBatchService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</Services>
</WorkflowWithTracking>
</configuration>
客户端代码:
static void Main(string[] args)
{
WorkflowRuntimeSection config;
config = ConfigurationManager.GetSection("WorkflowWithTracking") as WorkflowRuntimeSection;
//数据库连接串
strConn = config.CommonParameters["ConnectionString"].Value;
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime("WorkflowWithTracking"))
{
SqlTrackingService sts = new SqlTrackingService(strConn);
AutoResetEvent waitHandle = new AutoResetEvent(false);
workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); };
SharedConnectionWorkflowCommitWorkBatchService _shareConn = new SharedConnectionWorkflowCommitWorkBatchService(strConn);
if (workflowRuntime.GetService(_shareConn.GetType()) == null)
{
//加入数据连接共享服务
workflowRuntime.AddService(_shareConn );
}
if (workflowRuntime.GetService(sts.GetType()) == null)
{
//加入跟踪服务
workflowRuntime.AddService(sts);
}
SqlWorkflowPersistenceService perService = new SqlWorkflowPersistenceService(strConn);
if (workflowRuntime.GetService(perService.GetType()) == null)
{
//加入持久化服务
workflowRuntime.AddService(perService);
}
WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(ApproveWorkFlow.WorkflowConsole.Workflow1));
instance.Start();
waitHandle.WaitOne();
Console.WriteLine("---DumpTrackingEvents开始---");
DumpTrackingEvents(instance.InstanceId);
Console.WriteLine("---DumpTrackingEvents结束---");
Console.Read();
}
}
问题:我同时添加了持久化服务和跟踪服务,也启动了共享数据库连接服务,再次跟踪数据库,发现情况和之前的跟踪服务一样,这是我不明白的地方,希望哪位高手帮忙指点下。