公司最近要我這個菜鳥做Sharepoint工作流程。我對工作流程也是略懂,之前瞭解的都是皮毛。現在要我負責工作流程項目,所以現在拚老命學習。Sharepoint 2010的工作流程是基於WorkFlow 3.5的。所以我還在學習3.5。哎,人家都接觸4.0了。不廢話,今天學習Tracking。
1:Tracking簡介
工作流程運行時在執行工作流程時會引發某些事件。Tracing Service能夠捕獲工作流程執行期間引發的這些事件,而在執行期間可以查看工作流程的執行個體狀態。
這些事件
2:簡單樣本
先來一個簡單的樣本,看看這Tracking的用途,WorkFlow Foundation為我們提供了System.Workflow.Runtime.Tracking.SqlTrackingService類,這個類為我們提供了SQL 資料庫儲存跟蹤資訊的Tracing Service。這個執行個體化這個類需要傳遞一個資料庫連接字串。這個資料庫連接正是我們需要儲存跟蹤資訊的SQL SERVER 資料庫地址。那我們先建立SQL追蹤資料庫。
2-1:建立SQL追蹤資料庫
先建立一資料庫:
Create DataBase WFTracking
建立好資料庫WFTracking後,我們找到下面的兩個資料庫指令碼。並執行這兩個資料庫指令碼。
%WINDIR%\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\<語言>\Tracking_Schema.sql
%WINDIR%\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\<語言>\Tracking_Logic.sql。
2-2:
1: 建立一個3.5的順序工作流程控制台應用程式。
我們不添加任何的Activity
2:開啟Program.cs檔案,引用命名空間System.Workflow.Runtime.Tracking。
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;using System.Workflow.Runtime;using System.Workflow.Runtime.Hosting;using System.Workflow.Runtime.Tracking;namespace TrackingConsoleApp{ class Program { /// <summary> /// Tracking服務資料庫連結 /// </summary> static string strConn = "Initial Catalog=WFTracking;Data Source=localhost;Integrated Security=SSPI;"; static void Main(string[] args) { using (WorkflowRuntime workflowRuntime = new WorkflowRuntime()) { AutoResetEvent waitHandle = new AutoResetEvent(false); workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); }; workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e) { Console.WriteLine(e.Exception.Message); waitHandle.Set(); }; //註冊 SQL 追蹤服務 workflowRuntime.AddService(new SqlTrackingService(strConn)); WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(TrackingConsoleApp.Workflow1)); instance.Start(); waitHandle.WaitOne(); workflowRuntime.StopRuntime(); GetInstanceTrackingEvents(instance.InstanceId); GetActivityTrackingEvents(instance.InstanceId); } } static void GetInstanceTrackingEvents(Guid instanceId) { SqlTrackingQuery sqlTrackingQuery = new SqlTrackingQuery(strConn); //擷取工作流程執行個體 SqlTrackingWorkflowInstance sqlTrackingWorkflowInstance; sqlTrackingQuery.TryGetWorkflow(instanceId, out sqlTrackingWorkflowInstance); if (sqlTrackingWorkflowInstance != null) { Console.WriteLine("\n執行個體級事件:\n"); foreach (WorkflowTrackingRecord workflowTrackingRecord in sqlTrackingWorkflowInstance.WorkflowEvents) { Console.WriteLine("TrackingWorkflowEvent : {0} EventDateTime : {1}", workflowTrackingRecord.TrackingWorkflowEvent, workflowTrackingRecord.EventDateTime); } } } static void GetActivityTrackingEvents(Guid instanceId) { SqlTrackingQuery sqlTrackingQuery = new SqlTrackingQuery(strConn); SqlTrackingWorkflowInstance sqlTrackingWorkflowInstance; sqlTrackingQuery.TryGetWorkflow(instanceId, out sqlTrackingWorkflowInstance); if (sqlTrackingWorkflowInstance != null) { Console.WriteLine("\n活動級事件:\n"); foreach (ActivityTrackingRecord activityTrackingRecord in sqlTrackingWorkflowInstance.ActivityEvents) { Console.WriteLine("ExecutionStatus : {0} EventDateTime : {1} QualifiedName : {2}", activityTrackingRecord.ExecutionStatus, activityTrackingRecord.EventDateTime, activityTrackingRecord.QualifiedName); } } } }}
註:
SqlTrackingQuery能夠在追蹤資料庫中擷取某些種類的跟蹤資料。SqlTrackingQuery.TryGetWorkflow方法則嘗試擷取工作流程執行個體在SQL資料庫中的跟蹤資料。
也可以在App.config裡面佈建服務:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<section name="WorkflowRuntime"
type="System.Workflow.Runtime.Configuration.WorkflowRuntimeSection,
System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<WorkflowRuntime>
<CommonParameters>
<!--Add parameters common to all services-->
<add name="ConnectionString"
value="Initial Catalog=WFTracking;Data Source=localhost;Integrated Security=SSPI;" />
</CommonParameters>
<Services>
<!--Add core services here-->
<add type="System.Workflow.Runtime.Tracking.SqlTrackingService,
System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35"/>
</Services>
</WorkflowRuntime>
</configuration>
運行這個程式。這裡可以看到在哪個時間,工作流程執行了哪些事件。可我看到時間貌似和我電腦的時間對不上。呵,這是因為資料庫的時間格式是GMT格式。GMT比我們中國晚8個小時。這樣解決了不同時區伺服器時差的問題。
2-3:簡單樣本後延伸……
我們修改工作流程,我們添加一個Activity到工作流程。
private void codeActivity1_ExecuteCode(object sender, EventArgs e){ Console.WriteLine("Run CodeActivity1");}再次運行程式。杯具,出現錯誤。問題很明顯,沒有找到我們剛加的codeActivity1。
在註冊SqlTrackingServices後,WorkFlowRuntime載入工作流程時,會先在追蹤資料庫尋找該工作流程的資訊,如果沒有則存入資料庫,如果有它也不會更新資料庫的工作流程資訊。解決方式是刪除資料庫中原有的資訊,或修改工作流程類名。我們最常用的方法是修改工作流程的版本,即修改程式集版本號碼即可。
2-4:使用者跟蹤事件
User Track Point是我們在工作流程或自訂活動中加入的。如何添加使用者跟蹤呢?只需要使用TrackData方法,這樣會被Tracing Service記錄儲存在資料。
private void 第1個Code_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("第1個Code_ExecuteCode");
this.TrackData("第1個Code:" + DateTime.Now.ToString());
}
擷取使用者跟蹤:
private static void GetUserTrackingRecords(System.Guid instanceId)
{
SqlTrackingQuery query = new SqlTrackingQuery(strConn);
SqlTrackingWorkflowInstance WFInstance;
query.TryGetWorkflow(instanceId, out WFInstance);
foreach (UserTrackingRecord userTR in WFInstance.UserEvents)
{
Console.WriteLine("====================================");
Console.WriteLine("所屬Activity:" + userTR.QualifiedName);
Console.WriteLine("Activity類型:" + userTR.ActivityType.ToString());
Console.WriteLine("上下文ID:" + userTR.ContextGuid.ToString());
Console.WriteLine("時間: " + userTR.EventDateTime.ToString());
Console.WriteLine("內容:" + userTR.UserData.ToString());
Console.WriteLine("EventOrder欄位值:" + userTR.EventOrder.ToString());
Console.WriteLine("Parent上下文ID:" + userTR.ParentContextGuid.ToString());
try { Console.WriteLine("索引值對:" + userTR.UserDataKey.ToString()); }
catch { Console.WriteLine("該條無索引值對!"); }
Console.WriteLine();
}
}