玄铁剑

成功的途径:抄,创造,研究,发明...
posts - 128, comments - 42, trackbacks - 0, articles - 174

WF创建完整的持久服务及跟踪服务过程

Posted on 2008-06-29 10:48 玄铁剑 阅读(514) 评论(0)  编辑 收藏 引用 所属分类: asp.netWF

任务 1:使用代码配置运行时服务

在此任务中,您要学习如何使用在 WorkflowRuntime 类中定义的方法向 Windows Workflow Foundation 添加服
务。 在此任务以及下一项任务中,只使用 DefaultWorkflowSchedulerService 类。 从任务 3:使用 Windows 工
作流持久性服务开始,您要学习如何使用 Windows Workflow Foundation 提供的其他服务。

Note注意:

虽然建议您按顺序进行下列练习,但并不要求您这么做。 您可以通过打开示例项目并执行下节中的步骤
来开始此练习。

添加运行时服务

  1. Program 文件中,导入 System.Workflow.Runtime.Tracking 命名空间以便您可以使用该命名空间中的类型。

    C# 

    using System.Workflow.Runtime.Tracking;
                    
  2. Program 类中,创建一个名为 maxSimultaneousWorkflows 的静态 Int32 字段,并将它的值指定为 1。

    C# 

    static int maxSimultaneousWorkflows = 1;
                    
  3. 在使用 Program 类定义的 Main 方法中,将 DefaultWorkflowSchedulerService 添加到 WorkflowRuntime

    使用 AddService 方法,并传递 DefaultWorkflowSchedulerService 可以计划的最大同时工作流数作为参数。

    C# 

    workflowRuntime.AddService(
                    new DefaultWorkflowSchedulerService(maxSimultaneousWorkflows));
                    

编译代码

有关编译代码的信息,请参见编译代码。

在任务 2:使用 App.Config 配置运行时服务中,您要使用应用程序配置文件向 Windows

任务 2:使用 App.Config 配置运行时服务

在任务 1:使用代码配置运行时服务中,您通过调用在 WorkflowRuntime 类中定义的 AddService 方法将 DefaultWorkflowSchedulerService 服务添加到了 Windows Workflow Foundation 运行时引擎。 在此练习中,您要使用不同的方法来配置运行时服务,即使用应用程序配置文件。

使用配置文件是一种更加灵活的替代方案,原因是:通过这种方法,您可以为 Windows Workflow 运行时引擎创建您的应用程序可以使用的多种不同配置。 例如,您可以创建不使用任何服务的配置,也可以创建在工作流执行期间使用持久性和跟踪功能的运行时引擎配置。 此外,可在同一配置文件中定义这些不同的配置,并由主机应用程序根据需要对访问这些配置。

Note注意:

如果已完成任务 1:使用代码配置运行时服务,则必须撤消您对项目所做的全部更改,因为您要使用配置文件配置运行时服务。 此任务提供的项目文件不包含在上一任务中添加的代码,因此可提供一个良好起点。

Note注意:

虽然建议您按顺序进行下列练习,但并不要求您这么做。 您可以通过打开示例项目并执行下节中的步骤
来开始此练习。

创建应用程序配置文件

  1. 在项目目录中创建一个名为 App.config 的新文件。

  2. 在 HostingWorkflows 项目文件中包含您的源文件的 ItemGroup 元素中,添加一个名为 None 的新元素。

  3. 添加一个名为 Include 且值为“App.config”的属性。

定义应用程序配置文件

  1. 在 App.config 文件中,使用 UTF-8 编码创建标准 XML 处理指令。

     
    <?xml version="1.0" encoding="utf-8" ?>
  2. 创建一个名为 configuration 的根元素。

     
    <configuration>
                    </configuration>
  3. configuration 元素中,创建一个名为 configSections 的新元素。

     
    <configSections>
                    </configSections>
  4. configSections 元素中,创建一个名为 section 的新元素。

  5. 添加一个名为 name 且值为“HostingWorkflowRuntime”的属性。

  6. 另外添加一个名为 type 且值为 "System.Workflow.Runtime.Configuration.WorkflowRuntimeSection, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 的属性。

     
    <section name="HostingWorkflowRuntime" 
    type="System.Workflow.Runtime.Configuration.WorkflowRuntimeSection,
    System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral,
    PublicKeyToken=31bf3856ad364e35" />
    Note注意:

    您可以根据需要创建任意数量的配置节。 但是,对于此练习,只须创建一个配置节。

  7. configuration 节点中创建一个名为 HostingWorkflowRuntime 的新元素(包含一个名为 name 且值为“Hosting”的属性)。

    Note注意:

    此元素名与您通过在步骤 5 中创建的节的 name 属性指定的名称相同。如果您创建多个配置
    节,则创建与每个节名相对应的新元素。

     
    <HostingWorkflowRuntime Name="Hosting">
                    </HostingWorkflowRuntime>
  8. HostingWorkflowRuntime 元素中,创建一个名为 CommonParameters 的新元素。

     
    <CommonParameters/>
  9. HostingWorkflowRuntime 元素中,创建一个名为 Services 的新元素。

     
    <Services>
                    </Services>
  10. Services 元素中,创建一个名为 add 的新元素。

  11. 添加一个名为 type 且值为 System.Workflow.Runtime.Hosting.DefaultWorkflowSchedulerService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 的属性。

  12. 另外添加一个名为 maxSimultaneousWorkflows 且值为 1 的属性。

     
    <add type="System.Workflow.Runtime.Hosting.DefaultWorkflowSchedulerService, 
    System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral,
    PublicKeyToken=31bf3856ad364e35" maxSimultaneousWorkflows="1"/>
  13. App.config 文件看上去与以下配置相似。

     
    <?xml version="1.0" encoding="utf-8" ?>
                    <configuration>
                    <configSections>
                    <section name="HostingWorkflowRuntime" 
    type="System.Workflow.Runtime.Configuration.WorkflowRuntimeSection,
    System.Workflow.Runtime, Version=3.0.00000.0,
    Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> </configSections> <HostingWorkflowRuntime Name="Hosting"> <CommonParameters/> <Services> <add type="System.Workflow.Runtime.Hosting.DefaultWorkflowSchedulerService,
    System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral,
    PublicKeyToken=31bf3856ad364e35" maxSimultaneousWorkflows="1"/> </Services> </HostingWorkflowRuntime> </configuration>

使用应用程序配置文件

  • Program 类的 Main 方法中,为 WorkflowRuntime 构造函数(用于实例化 WorkflowRuntime 对象)添加一个参数。

    此参数属于 String 类型,该类型指定要使用的配置节的名称。

编译代码

有关编译代码的信息,请参见编译代码。

在任务 3:使用 Windows 工作流持久性服务中,您要学习如何使用 SqlWorkflowPersistenceService 服务存储工作流的当前状态。


 

任务 3:使用 Windows 工作流持久性服务

在本任务中,您将了解如何在应用程序中使用 SqlWorkflowPersistenceService 服务。 如果程序集在一段时间空闲(在本示例中,这种情况在 DelayActivity 活动运行时发生),Windows Workflow Foundation 可以在工作流必须继续运行之前,将它保持到存储中。

SqlWorkflowPersistenceService 服务使用 SQL Server 数据库通过一个称为“卸载”的过程存储工作流的当前状态。 当工作流准备好继续运行时,SqlWorkflowPersistenceService 服务通知 Windows Workflow Foundation 运行时引擎,然后加载工作流,之后继续执行。

Note注意:

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

Note注意:

这些服务所需的数据库不由 Windows Workflow Foundation 安装程序安装;但是,Windows Workflow
Foundation 安装程序会安装用于为这些服务创建和配置数据库的 SQL 脚本。

Note 注意:

必须有 App.config 文件才能执行此任务。 如果不遵循任务 2:使用 App.Config 配置运行时服务中的步
骤,则必须先创建 App.config 文件,然后才能继续。

Note注意:

虽然建议您按顺序进行下列练习,但并不要求您这么做。 您可以通过打开示例项目并执行下节中的步
骤来开始此练习。

创建 SQL 持久性数据库

  1. 在 Microsoft SQL Server 2005 Express、Microsoft SQL Server 2000 或更高版本或者 Microsoft SQL Server 2000 Desktop Engine (MSDE) 中,使用下面的 SQL 查询语句来新建一个名为 WorkflowPersistenceStore 的数据库。

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

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

  4. 单击“执行”运行查询或按 F5 创建 SQL 持久性服务表。

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

  6. 单击“执行”运行查询或按 F5 创建 SQL 持久性服务存储过程。

针对 SqlWorkflowPersistenceService 修改 App.config

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

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

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

  4. add 元素添加名为 LoadIntervalSeconds 的属性,该属性的值为 5

    <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;" LoadIntervalSeconds="5"/>

创建额外的工作流事件处理程序

  1. Program 类的 Main 方法中,为 WorkflowLoaded 事件添加一个新的事件处理程序。

    C# 

    workflowRuntime.WorkflowLoaded += new
                    EventHandler<WorkflowEventArgs>(workflowRuntime_WorkflowLoaded);
                    
  2. Program 类的 Main 方法中,为 WorkflowIdled 事件添加一个新的事件处理程序。

    C# 

    workflowRuntime.WorkflowIdled += new
                    EventHandler<WorkflowEventArgs>(workflowRuntime_WorkflowIdled);
                    
  3. Program 类的 Main 方法中,为 WorkflowPersisted 事件添加一个新的事件处理程序。

    C# 

    workflowRuntime.WorkflowPersisted += new
                    EventHandler<WorkflowEventArgs>(workflowRuntime_WorkflowPersisted);
                    
  4. Program 类的 Main 方法中,为 WorkflowUnloaded 事件添加一个新的事件处理程序。

    C# 

    workflowRuntime.WorkflowUnloaded += new
                    EventHandler<WorkflowEventArgs>(workflowRuntime_WorkflowUnloaded);
                    
  5. 新建一个名为 workflowRuntime_WorkflowLoaded 的静态方法。

    在方法体中,使用 WriteLine 方法显示一条信息性消息。

    C# 

    static void workflowRuntime_WorkflowLoaded(object sender, WorkflowEventArgs e)
                    {
                    Console.WriteLine("Workflow {0} loaded", e.WorkflowInstance.InstanceId);
                    }
                    
  6. 新建一个名为 workflowRuntime_WorkflowIdled 的静态方法。

  7. 在方法体中,使用 WriteLine 方法显示一条信息性消息。

  8. 调用在 WorkflowEventArgs 参数中的 WorkflowInstance 对象中定义的 Unload 方法。

    Note注意:

    这里介绍的在工作流空闲时卸载 WorkflowInstance 的方法使您可以在保持工作流之前,先执行特定于应用程序的逻辑。 如果您不需要这一类型的功能,应在应用程序的 App.config 文件的 SqlWorkflowPersistenceService 元素中添加一个名为 UnloadOnIdle 的属性,并将该属性设置为 true

    C# 

    static void workflowRuntime_WorkflowIdled(object sender, WorkflowEventArgs e)
                    {
                    Console.WriteLine("Workflow {0} idled", e.WorkflowInstance.InstanceId);
                    e.WorkflowInstance.Unload();
                    }
                    
  9. 新建一个名为 workflowRuntime_WorkflowPersisted 的静态方法。

    在方法体中,使用 WriteLine 方法显示一条信息性消息。

    C# 

    static void workflowRuntime_WorkflowPersisted(object sender, WorkflowEventArgs e)
                    {
                    Console.WriteLine("Workflow {0} persisted", e.WorkflowInstance.InstanceId);
                    }
                    
  10. 新建一个名为 workflowRuntime_WorkflowUnloaded 的静态方法。

    在方法体中,使用 WriteLine 方法显示一条信息性消息。

    C# 

    static void workflowRuntime_WorkflowUnloaded(object sender, WorkflowEventArgs e)
                    {
                    Console.WriteLine("Workflow {0} unloaded", e.WorkflowInstance.InstanceId);
                    }
                    
  11. 新建一个名为 UnloadInstance 的静态方法,该方法采用一个名为 workflowInstanceObject 作为参数。

  12. UnloadInstance 方法中,将 workflowInstance 参数强制转换为 WorkflowInstance 对象,并调用 Unload 方法来保持工作流。

    C# 

    static void UnloadInstance(object sender, WorkflowEventArgs e)
                    {
                    Console.WriteLine("Workflow {0} unloaded", e.WorkflowInstance.InstanceId);
                    e.WorkflowInstance.Unload();
                    }
                    
  13. 生成项目并运行应用程序。

    输出应当与下图类似。

    完成任务 3 后的输出

编译代码

有关编译代码的信息,请参见编译代码。

在任务 4:使用 Windows 工作流跟踪服务中,您将了解如何使用 SqlTrackingService 来跟踪工作流实例和在运行工作流期间发生的活动事件。

任务 4:使用 Windows 工作流跟踪服务

在上一任务中,通过启用 SqlWorkflowPersistenceService 服务在工作流进入空闲状态时保持工作流。

在本任务中,将使用 SqlTrackingService 服务来跟踪工作流实例和在运行工作流时发生的活动事件。 通过使用在 WorkflowRuntime 中定义的 AddService 方法来添加 SqlTrackingService 服务,以使用 SqlTrackingQuery 类。

工作流结束运行时,可以使用 SqlTrackingQuery 类从跟踪数据库中提取跟踪信息。 在创建 SqlTrackingQuery 类的实例(传递正在使用的跟踪数据库的连接字符串)时,可以通过访问 SqlTrackingWorkflowInstance 对象的 ActivityEvents 属性来枚举每个跟踪记录。 这包含 ActivityTrackingRecord 对象的集合,这些对象用于查看工作流中的活动的跟踪信息。 此外,可以通过访问在 SqlTrackingWorkflowInstance 类中定义的 WorkflowEvents 属性来使用相同的过程跟踪工作流实例事件。

Note注意:

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

Note注意:

这些服务所需的数据库不由 Windows Workflow Foundation 安装程序安装;但是,Windows Workflow
Foundation 安装程序会安装用于为这些服务创建和配置数据库的 SQL 脚本。

Note注意:

虽然建议您按顺序进行下列练习,但并不要求您这么做。 您可以通过打开示例项目并执行下节中的步骤
来开始此练习。 此外,若要让项目正常运行,必须创建应用程序所使用的持久性数据库。 为此,请执
行任务 3:使用 Windows 工作流持久性服务中的过程“创建 SQL 持久性数据库”。

创建 SQL 跟踪数据库

  1. 在 Microsoft SQL Server 2005 Express、Microsoft SQL Server 2000 或更高版本或者 Microsoft SQL Server 2000 Desktop Engine (MSDE) 中,使用下面的 SQL 查询语句来创建一个名为 WorkflowTrackingStore 的新数据库。

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

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

  4. 通过单击“执行”或按 F5 来运行查询,以便创建 SQL 跟踪服务表。

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

  6. 通过单击“执行”或按 F5 来运行查询,以便创建 SQL 跟踪服务存储过程。

导入 SQL 命名空间

  • 将下列指令添加到包含 Program 类的文件中,以导入使用跟踪和 SqlTrackingQuery 类所需的类型。

    C# 

    using System.Workflow.Runtime.Tracking;
                    using System.Data;
                    using System.Data.SqlClient;
                    using System.Data.SqlTypes;
                    

修改 SqlTrackingService 的 App.config

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

  2. add 元素中,添加一个名为 type 的属性,该属性具有 System.Workflow.Runtime.Tracking.SqlTrackingService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 值。

  3. add 元素中,添加一个名为 connectionString 的属性,该属性具有 Initial Catalog=WorkflowTrackingStore;Data Source=localhost;Integrated Security=SSPI;

     
    <add type="System.Workflow.Runtime.Tracking.SqlTrackingService, 
    System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral,
    PublicKeyToken=31bf3856ad364e35"
    connectionString="Initial Catalog=WorkflowTrackingStore;Data Source=localhost;
    Integrated Security=SSPI;"/>

跟踪工作流事件

  1. 在您的项目的 Program 类中,创建一个名为 connectionStringString 类型的新静态字段。

    为该字段指定 “Initial Catalog=WorkflowTrackingStore;Data Source=localhost;Integrated Security=SSPI;” 值。

    C# 

    public static string connectionString =
                    "Initial Catalog=WorkflowTrackingStore;" +
                    "Data Source=localhost;Integrated Security=SSPI;";
                    
  2. 在您的项目的 Program 类中,创建一个名为 GetInstanceTrackingEvents 的新静态方法,该方法接受名为 instanceIdGuid 参数。

  3. GetInstanceTrackingEvents 方法中创建一个新的 SqlTrackingQuery 对象,将 connectionString 变量作为参数传递给构造函数。

  4. 创建一个名为 sqlTrackingWorkflowInstanceSqlTrackingWorkflowInstance 变量,并将该对象与 instanceId 参数一起传递给在 SqlTrackingQuery 对象中定义的 TryGetWorkflow 方法。 TryGetWorkflow 方法返回一个指示成功或失败的布尔值。 如果该方法返回 false,则输出一条错误消息并从该方法返回。

  5. 枚举在 sqlTrackingWorkflowInstance 对象中定义的 WorkflowEvents 集合中包含的每个 WorkflowTrackingRecord

    使用 WriteLine 方法显示 TrackingWorkflowEventEventDateTime 属性。 GetInstanceTrackingEvents 应当与下面的代码类似:

    C# 

    static void GetInstanceTrackingEvents(Guid instanceId)
              {
                    SqlTrackingQuery sqlTrackingQuery = new SqlTrackingQuery(connectionString);
                    SqlTrackingWorkflowInstance sqlTrackingWorkflowInstance;
                    if (!sqlTrackingQuery.TryGetWorkflow(instanceId, out sqlTrackingWorkflowInstance))
                    {
                    Console.WriteLine("Could not retrieve SqlTrackingWorkflowInstance");
                    }
                    else
                    {
                    Console.WriteLine("\nInstance Level Events:\n");
                    foreach (WorkflowTrackingRecord workflowTrackingRecord in
                    sqlTrackingWorkflowInstance.WorkflowEvents)
                    {
                    Console.WriteLine("EventDescription : {0}  DateTime : {1}",
                    workflowTrackingRecord.TrackingWorkflowEvent,
                    workflowTrackingRecord.EventDateTime);
                    }
                    }
                    }

     

    Visual Basic 

    Private Shared Sub GetInstanceTrackingEvents(ByVal instanceId As Guid)
                    Dim sqlTrackingQuery As SqlTrackingQuery = _
                    New SqlTrackingQuery(connectionString)
                    Dim sqlTrackingWorkflowInstance As SqlTrackingWorkflowInstance = Nothing
                    If sqlTrackingQuery.TryGetWorkflow(instanceId, sqlTrackingWorkflowInstance) = False Then
                    Console.WriteLine("Could not retrieve SqlTrackingWorkflowInstance")
                    Else
                    Console.WriteLine(Constants.vbLf & "Instance Level Events:" & Constants.vbLf)
                    For Each workflowTrackingRecord As WorkflowTrackingRecord In _
                    sqlTrackingWorkflowInstance.WorkflowEvents
                    Console.WriteLine("EventDescription : {0}  DateTime : {1}", _
                    workflowTrackingRecord.TrackingWorkflowEvent, _
                    workflowTrackingRecord.EventDateTime)
                    Next workflowTrackingRecord
                    End If
                    End Sub
  6. Program 类的 Main 方法中,在 StopRuntime 方法调用的后,调用刚才创建的 GetInstanceTrackingEvents 方法,并将 workflowInstance 对象的 InstanceId 属性作为参数传递。

    C# 

    GetInstanceTrackingEvents(workflowInstance.InstanceId);
                    

跟踪活动事件

  1. 在您的项目的 Program 类中,创建一个名为 GetActivityTrackingEvents 的新静态方法,该方法接受名为 instanceIdGuid 参数。

  2. GetActivityTrackingEvents 方法中创建一个新的 SqlTrackingQuery 对象,将 connectionString 变量作为参数传递给构造函数。

  3. 创建一个名为 sqlTrackingWorkflowInstanceSqlTrackingWorkflowInstance 变量,并将该对象与 instanceId 参数一起传递给在 SqlTrackingQuery 对象中定义的 TryGetWorkflow 方法。 TryGetWorkflow 方法返回一个指示成功或失败的布尔值。 如果该方法返回 false,则输出一条错误消息并从该方法返回。

枚举在 sqlTrackingWorkflowInstance 对象中定义的 ActivityEvents 集合中包含的每个 ActivityTrackingRecord

使用 WriteLine 方法显示 activityTrackingRecord 对象的 ExecutionStatusEventDateTimeQualifiedName 属性。 GetActivityTrackingEvents 方法应当与下面的代码类似:

C# 

static void GetActivityTrackingEvents(Guid instanceId)
            {
            SqlTrackingQuery sqlTrackingQuery = new SqlTrackingQuery(connectionString);
            SqlTrackingWorkflowInstance sqlTrackingWorkflowInstance;
            if (!sqlTrackingQuery.TryGetWorkflow(instanceId, out sqlTrackingWorkflowInstance))
            {
            Console.WriteLine("Could not retrieve SqlTrackingWorkflowInstance");
            }
            else
            {
            Console.WriteLine("\nActivity Tracking Events:\n");
            foreach (ActivityTrackingRecord activityTrackingRecord in
            sqlTrackingWorkflowInstance.ActivityEvents)
            {
            Console.WriteLine(
            "StatusDescription: {0}  DateTime: {1} Activity Qualified ID: {2}",
            activityTrackingRecord.ExecutionStatus,
            activityTrackingRecord.EventDateTime,
            activityTrackingRecord.QualifiedName);
            }
            }
            }

 

Visual Basic 

Private Shared Sub GetActivityTrackingEvents(ByVal instanceId As Guid)
            Dim sqlTrackingQuery As SqlTrackingQuery = _
            New SqlTrackingQuery(connectionString)
            Dim sqlTrackingWorkflowInstance As SqlTrackingWorkflowInstance = Nothing
            If sqlTrackingQuery.TryGetWorkflow(instanceId, sqlTrackingWorkflowInstance) = False Then
            Console.WriteLine("Could not retrieve SqlTrackingWorkflowInstance")
            Else
            Console.WriteLine(Constants.vbLf & "Activity Tracking Events:" & _
            Constants.vbLf)
            For Each activityTrackingRecord As ActivityTrackingRecord In _
            sqlTrackingWorkflowInstance.ActivityEvents
            Console.WriteLine( _
            "StatusDescription: {0}  DateTime: {1} Activity Qualified ID: {2}", _
            activityTrackingRecord.ExecutionStatus, _
            activityTrackingRecord.EventDateTime, _
            activityTrackingRecord.QualifiedName)
            Next activityTrackingRecord
            End If
            End Sub

  1. Program 类的 Main 方法中,在 StopRuntime 方法调用后,调用刚才创建的 GetActivityTrackingEvents 方法,并将 workflowInstance 对象的 InstanceId 属性作为参数传递。

    C# 
    GetActivityTrackingEvents(workflowInstance.InstanceId);
                    
  2. 生成项目并运行应用程序。

    输出将类似下图。

    任务 4 的输出

编译代码

任务 5:创建跟踪配置文件

跟踪配置文件用于控制 Windows Workflow Foundation 运行时引擎生成的跟踪信息的类型。 默认情况下,您使用默认配置文件时,会为每个工作流和活动事件保存跟踪信息。

在本任务中,您创建跟踪所有工作流事件和活动事件的自定义跟踪配置文件(但仅限于 CodeActivity 活动)。 使用配置文件时,工作流中的任何其他活动不会生成任何跟踪信息。

Note注意:

虽然建议您按顺序进行下列练习,但并不要求您这么做。 您可以通过打开示例项目并执行下节中的步骤
来开始此练习。

导入命名空间

  • Program 源文件中,添加以下指令以导入跟踪配置文件所必须具有的类型。

    C# 

    using System.IO;
                    using System.Globalization;
                    using System.Workflow.ComponentModel;
                    using System.Workflow.Activities;
                    

创建跟踪配置文件

  1. 在项目的 Program 类中,创建名为 CreateTrackingProfile 的静态方法。

    Visual Basic 

    Private Shared Sub CreateTrackingProfile()
                    End Sub

     

    C# 

    static void CreateTrackingProfile()
                    {
                    }
  2. 在您在步骤 1 中创建的 CreateTrackingProfile 方法中,创建名为 profileTrackingProfile 对象和名为 trackPointActivityTrackPoint 对象。 另外,将 TrackingProfile 对象的 Version 属性设置为等于 Version 对象的新实例,将字符串“1.0.0.0”作为参数传递给构造函数。

    C# 

    TrackingProfile profile = new TrackingProfile();
                    ActivityTrackPoint trackPoint = new ActivityTrackPoint();
                    profile.Version = new Version("1.0.0.0");
                    
  3. 创建名为 locationActivityTrackingLocation 对象,将 CodeActivity 活动的 Type 作为参数传入构造函数。

    C# 

    // track CodeActivity activities only
                    ActivityTrackingLocation location = new ActivityTrackingLocation
                    (typeof(CodeActivity));
                    
  4. 依次枚举 ActivityExecutionStatus 枚举数据类型中的值,并将这些值添加到在 ActivityTrackingLocation 对象中定义的 ExecutionStatusEvents 集合。

    C# 

    // add all activity tracking events
                    foreach (ActivityExecutionStatus s in
                    Enum.GetValues(typeof(ActivityExecutionStatus)))
                    {
                    location.ExecutionStatusEvents.Add(s);
                    }
                    
  5. ActivityTrackingLocation 对象添加到在 ActivityTrackPoint 对象中定义的 MatchingLocations 集合。

  6. ActivityTrackPoint 对象添加到在 TrackingProfile 对象中定义的 ActivityTrackPoints 集合。

    C# 

    trackPoint.MatchingLocations.Add(location);
                    profile.ActivityTrackPoints.Add(trackPoint);
                    
  7. 创建一个名为 wtp 的新 WorkflowTrackPoint 对象和一个名为 wtlWorkflowTrackingLocation 对象。

    C# 

    WorkflowTrackPoint wtp = new WorkflowTrackPoint();
                    WorkflowTrackingLocation wtl = new WorkflowTrackingLocation();
                    
  8. 依次枚举 TrackingWorkflowEvent 枚举数据类型中的值,并将每个值添加到在 WorkflowTrackingLocation 对象中定义的 Events 集合。

    C# 

    // add all workflow tracking events
                    foreach (TrackingWorkflowEvent s in
                    Enum.GetValues(typeof(TrackingWorkflowEvent)))
                    {
                    wtl.Events.Add(s);
                    }
                    
  9. 将在 WorkflowTrackPoint 对象中定义的 MatchingLocation 属性设置为 WorkflowTrackingLocation 对象。

  10. WorkflowTrackPoint 对象添加到在 TrackingProfile 对象中定义的 WorkflowTrackPoints 集合。

    C# 

    wtp.MatchingLocation = wtl;
                    profile.WorkflowTrackPoints.Add(wtp);
                    
  11. 创建一个名为 serializer 的新 TrackingProfileSerializer 对象和一个名为 writerStringWriter 对象。

    C# 

    // serialize tracking profile and save to SQL
                    TrackingProfileSerializer serializer = new TrackingProfileSerializer();
                    StringWriter writer = new StringWriter(new StringBuilder(),
                    CultureInfo.InvariantCulture);
                    
  12. 通过调用在 TrackingProfileSerializer 类中定义的 Serialize 方法,序列化 TrackingProfile 对象。

    StringWriterTrackingProfile 对象作为参数传递给该方法。

    C# 

    serializer.Serialize(writer, profile);
                    
  13. 调用 InsertTrackingProfile 方法,将 writer.ToString() 作为参数传递给该方法。

    Note注意:

    在下一过程中创建 InsertTrackingProfile 方法。

    C# 

    InsertTrackingProfile(writer.ToString());
                    
  14. Program 类的 Main 方法中,调用您刚刚创建的 CreateTrackingProfile 方法。 此方法应在您创建 WorkflowRuntime 对象之前调用。

    C# 

    CreateTrackingProfile();
                    

将跟踪配置文件保存到 SQL 数据库

  1. 在项目的 Program 类中,创建名为 InsertTrackingProfile 的新静态方法,该方法采用名为 profileString 作为参数。

    Visual Basic 

    Private Shared Sub InsertTrackingProfile(ByVal profile As String)
                    End Sub

     

    C# 

    static void InsertTrackingProfile(string profile)
                    {
                    }
  2. InsertTrackingProfile 方法中,创建名为 cmd 的新 SqlCommand 对象。

    C# 

    SqlCommand cmd = new SqlCommand();
                    
  3. 使用您在上一步中创建的 SqlCommand 对象,将 CommandType 属性设置为 CommandType.StoredProcedure,将 CommandText 属性设置为“dbo.UpdateTrackingProfile”。

  4. 创建一个新 SqlConnection 对象,将 Program.connectionString 作为参数传递给构造函数,并将此对象分配给在 SqlCommand 对象中定义的 Connection 属性。

    C# 

    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.CommandText = "dbo.UpdateTrackingProfile";
                    cmd.Connection = new SqlConnection(Program.connectionString);
                    
  5. 创建一个新 try 块并将步骤 6 至 15 的代码放在该块中。

  6. 创建一个名为 typFullName 的新 SqlParameter 对象并设置其属性,如下表所示。

    属性名 属性值

    ParameterName

    “@TypeFullName”

    SqlDbType

    SqlDbType.NVarChar

    SqlValue

    typeof(Microsoft.Samples.Workflow.Tutorials.Hosting.HostingWorkflows).ToString();

  7. SqlParameter 对象添加到在 SqlCommand 对象中定义的 Parameters 集合。

    用于 typFullName 对象的代码看起来类似于下面的代码。

    C# 

    SqlParameter typFullName = new SqlParameter();
                    typFullName.ParameterName = "@TypeFullName";
                    typFullName.SqlDbType = SqlDbType.NVarChar;
                    typFullName.SqlValue = typeof(HostingWorkflows).ToString();
                    cmd.Parameters.Add(typFullName);
                    
  8. 创建一个名为 assemblyFullName 的新 SqlParameter 对象并设置其属性,如下表所述。

    属性名 属性值

    ParameterName

    “@AssemblyFullName”

    SqlDbType

    SqlDbType.NVarChar

    SqlValue

    typeof(Microsoft.Samples.Workflow.Tutorials.Hosting.HostingWorkflows).Assembly.FullName

  9. SqlParameter 对象添加到在 SqlCommand 对象中定义的 Parameters 集合。

    用于 assemblyFullName 对象的代码看起来类似于下面的代码。

    C# 

    SqlParameter assemblyFullName = new SqlParameter();
                    assemblyFullName.ParameterName = "@AssemblyFullName";
                    assemblyFullName.SqlDbType = SqlDbType.NVarChar;
                    assemblyFullName.SqlValue = typeof(HostingWorkflows).Assembly.FullName;
                    cmd.Parameters.Add(assemblyFullName);
                    
  10. 创建一个名为 versionId 的新 SqlParameter 对象并设置其属性,如下表所示。

    属性名 属性值

    ParameterName

    “@Version”

    SqlDbType

    SqlDbType.VarChar

    SqlValue

    "1.0.0.0"

  11. SqlParameter 对象添加到在 SqlCommand 对象中定义的 Parameters 集合。

    用于 versionId 对象的代码看起来类似于下面的代码。

    C# 

    SqlParameter versionId = new SqlParameter();
                    versionId.ParameterName = "@Version";
                    versionId.SqlDbType = SqlDbType.VarChar;
                    versionId.SqlValue = "1.0.0.0";
                    cmd.Parameters.Add(versionId);
                    
  12. 创建一个名为 trackingProfile 的新 SqlParameter 对象并设置其属性,如下表所示。

    属性名 属性值

    ParameterName

    “@TrackingProfileXml”

    SqlDbType

    SqlDbType.NVarChar

    SqlValue

    profile

  13. SqlParameter 添加到在 SqlCommand 对象中定义的 Parameters 集合。

    用于 trackingProfile 对象的代码看起来类似于下面的代码。

    C# 

    SqlParameter trackingProfile = new SqlParameter();
                    trackingProfile.ParameterName = "@TrackingProfileXml";
                    trackingProfile.SqlDbType = SqlDbType.NVarChar;
                    trackingProfile.SqlValue = profile;
                    cmd.Parameters.Add(trackingProfile);
                    
  14. 调用在 SqlCommand 对象的 Connection 属性中定义的 Open 方法。

  15. 调用在 SqlCommand 对象中定义的 ExecuteNonQuery 方法,可运行存储的过程并保存您的跟踪配置文件。

    C# 

    cmd.Connection.Open();
                    cmd.ExecuteNonQuery();
                    
  16. 在步骤 5 至 15 中创建的 try 块之后,创建用于 SqlException 异常的新 catch 块。

  17. catch 块中,使用 WriteLine 方法显示在 SqlException 对象中定义的 Message 属性。

    另外,跟踪配置文件更改时,用新版本号添加说明更新跟踪配置文件所需的步骤的消息。

    C# 

    catch (SqlException e)
                    {
                    Console.WriteLine(e.Message);
                    Console.WriteLine("The Tracking Profile was not inserted. " +
                    "if you want to add a new Tracking Profile, modify the version " +
                    "string in the profile by specifying a higher version number.");
                    return;
                    }
                    
  18. 创建 finally 块并调用 Close 方法,随后调用在 SqlCommand 对象的 Connection 属性中定义的 Dispose 方法。

    C# 

    finally
                    {
                    if ((null != cmd) && (null != cmd.Connection) &&
                    (ConnectionState.Closed != cmd.Connection.State))
                    {
                    cmd.Connection.Close();
                    cmd.Connection.Dispose();
                    }
                    }
                    
  19. 生成您的项目并运行该项目。

    输出与下图类似。

    完成任务 5 后的输出

编译代码

有关编译代码的信息,请参见编译代码。

有关完整教程,请参见完整的 Windows Workflow Foundation 运行库宿主教程。

只有注册用户登录后才能发表评论。