程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WF從入門到精通(第五章):workflow跟蹤

WF從入門到精通(第五章):workflow跟蹤

編輯:關於.NET

學習完本章,你將掌握:

1.workflow的可選服務

2.創建一個事件跟蹤數據庫

3.激活事件跟蹤服務

4.創建一個自定義跟蹤

5.查看你的workflow的跟蹤信息

目前為止,我們看過workflow的一些基本對象。我們通過活動創建workflow任務,它們在執行時由WorkflowInstance對象進行管理。workflow實例由WorkflowRuntime編入隊列並進行控制。但WF不只是為我們提供了這些對象,它也為我們提供了一些服務來和這些對象一起協同工作。

可插拔(可選)服務

工作流服務是一些附加的軟件庫,你的工作流能使用它來完成它們的的任務。有些服務是非必須可選的,如本章介紹的跟蹤服務。而其它的服務需要你的工作流必須執行它。

一個可插拔服務是這樣一個服務,它能像照菜單點菜一樣被選中以執行特定任務。例如,有管理線程的服務、跟蹤的服務、事務服務等等。你可選擇那些適合你的工作流的服務。你甚至還能自己進行創建。

哪這些服務看起來像什麼?他們能為我們做什麼?表5-1列出了可獲取的基本服務,它很好地為你描述了這些可獲取的服務的概念,並告訴你他們能做什麼。

當中的大部分服務我們不會直接使用。我們普遍的用法是使用從這些基本服務派生出的服務。

表5-1 基本工作流服務 服務 功能 WorkflowPersistenceService 抽象基類,派生出所有持久化的服務。 WorkflowQueuingService 該基類為你提供了一些方法,使你能用來管理和一個工作流實例相關的工作流隊列。 WorkflowRuntimeService 抽象基類,派生出工作流運行時的內核服務。 WorkflowScheddulerService 所有在工作流運行時宿主上創建線程以運行工作流實例的類的基類。 WorkflowSubscriptionService 那些管理訂閱(Subscriptions)工作流運行時類的基類。 WorkflowTransactionService 所有事務服務的基類。 TrackingService 一個抽象基類,在跟蹤服務和運行時跟蹤基礎結構(infrastructure)間提供了基本的接口。

請記住這些是基類。我們使用的服務實際上從它們派生。例如,當我們運行一個工作流實例時,有時需為實例創建一個線程去使用。DefaultWorkflowSchedulerService正是做這個工作的,它使用WorkflowSchedulerService作為它的基類。但假如你想自己提供這個線程,你可使用ManualWorkflowSchedulerService代替。在本章中我們將看到由SqlTrackingService提供的跟蹤服務,它使用了TrackingService作為它的基類。

“可插拔(可選)”一詞部分來源於下面的情況:你可能考慮在任何時間上你都可能需要使用一個調度程序服務,運行時服務,入隊和訂閱(定時器)服務。但你還能在工作中進一步添加持久化和跟蹤服務,以及外部數據通信服務。

工作流跟蹤

在本章,我們將把重點放到跟蹤服務上。其它服務將在其它章節進行介紹。WF由一個主要的跟蹤服務——SqlTrackingService承載。但是假如你需要的話,也有兩個額外的服務可用。它們是ConsoleTrackingService和SimpleFileTrackingService,這二個服務允許你把跟蹤信息寫到控制台窗口或者文件中而不是Microsoft SQL Server數據庫。在這裡我們不會使用這兩種服務,但你需要的話你可使用它們。

使用SqlTrackingService進行工作流事件跟蹤

通過添加一個跟蹤服務(通常是SqlTrackingService)到工作流運行時中,你可跟蹤你的工作流的處理過程。假如你有特定的跟蹤需求,你也能創建你自定義的跟蹤事件。假如捕獲的事件為你提供了過多的跟蹤數據,你也能創建跟蹤配置文件來過濾這些跟蹤數據。

當跟蹤的事件激發時,WF創建並管理跟蹤記錄。盡管你不用做這些工作,但你還是能容易地從WF中直接訪問這些跟蹤記錄。你要知道這些信息也被記錄到數據庫中,因此直接從數據庫中檢索這些信息也是可能的。通常都在記錄這些跟蹤信息後的某個時間,使用一個象WorkflowMonitor或你自己設計的工具之類的外部跟蹤監控工具,來查詢這些跟蹤信息。

表5-2列出了在你的WF事件跟蹤中經常使用的對象,在本章我們將使用其中的一些。假如你需要自定義你的工作流事件跟蹤,那你應知道WF為你提供了一個和跟蹤相關對象的強大類庫。

表5-2 事件跟蹤對象

對象 功能   指定要從活動中提取並在跟蹤點匹配時與關聯的批注集合一起發送到跟蹤服務的屬性或字段。 ActivityTrackingCondition 表示一個條件,該條件通過使用指定的比較運算符將活動成員的值與指定值進行比較。 ActivityTrackingLocation 定義與根工作流實例的可能執行路徑中的某個活動狀態事件相對應的活動限定位置。 ActivityTrackingRecord 包含運行庫跟蹤基礎結構在 ActivityTrackPoint 匹配時發送到跟蹤服務的數據。它還用在 ActivityEvents 屬性的返回列表中。 ActivityTrackPoint 定義工作流實例的可能執行路徑中要跟蹤的點,該點與活動執行狀態更改關聯。 SqlTrackingQuery 包含用於管理跟蹤數據查詢的方法和屬性,跟蹤數據包含在 SqlTrackingService 使用的 SQL 數據庫中。 SqlTrackingQueryOptions 包含一些屬性,這些屬性用於約束 SqlTrackingQuery.GetWorkflows 調用所返回 SqlTrackingWorkflowInstance 對象的集合。 SqlTrackingWorkflowInstance 通過工作流實例的 SqlTrackingService 提供對SQL數據庫中保留的跟蹤數據的訪問 TrackingProfile 定義根工作流實例的可能執行路徑中的關注點,應將有關該關注點的信息通知跟蹤服務。它過濾跟蹤事件,並把過濾後的跟蹤記錄返回給某個跟蹤服務。這裡有三種類型的跟蹤事件能被過濾:活動狀態事件、工作流狀態事件和用戶事件。 UserTrackingLocation 定義與根工作流實例的可能執行路徑中的某個用戶事件相對應的活動限定位置。 UserTrackingRecord 包含運行庫跟蹤基礎結構在 UserTrackPoint 匹配時發送到跟蹤服務的數據。 UserTrackPoint 定義一個要跟蹤的點(與用戶事件關聯),該點位於根工作流實例的可能執行路徑中。 WorkflowDataTrackingExtract 指定要從工作流的根活動中提取,並在跟蹤點匹配時隨關聯的批注集合一起發送到跟蹤服務的屬性或字段。 WorkflowTrackingLocation 定義對發生在根工作流實例中的特定工作流事件的關注;用於按跟蹤配置文件中的 WorkflowTrackPoint 進行匹配。 WorkflowTrackingRecord 包含運行時跟蹤基礎結構在匹配了 WorkflowTrackPoint 時發送到跟蹤服務的數據。它還用在 WorkflowEvents 屬性的返回列表中。 WorkflowTrackPoint 定義一個與一組工作流狀態事件關聯的點,這些事件在根工作流實例的可能執行路徑中進行跟蹤。

這些對象可考慮歸為兩個大類:跟蹤數據檢索和跟蹤詳細說明。跟蹤檢索對象,如SqlTrackingQuery,一旦跟蹤數據被存儲到數據庫中,你可使用它們采集跟蹤數據。跟蹤詳細說明對象,如跟蹤點和位置對象,允許你能在工作流代碼中控制該跟蹤什麼。

 

像跟蹤點和位置對象之類的跟蹤詳細說明對象還可被歸為三大組:活動事件、工作流事件和用戶事件。和活動相關的跟蹤對象,如 ActivityTrackingPoint 或 ActivityTrackingLocation,用來記錄相關聯的活動的事件信息並保存到跟蹤數據庫中。這些事件包含如下這些:活動取消、未處理的異常和執行的事件。工作流事件跟蹤對象的工作方式和工作流相關的事件的工作方式相像(但工作流啟動和停止,實例的創建、空閒和完成及其它相似的相關聯的事件除外)。最後是用戶事件跟蹤,它用在自定義你特有的工作流跟蹤需求中指定你的工作流並完全依賴於你的工作流想怎樣進行跟蹤。在本章中當我們學習跟蹤配置文件時會看到它們中的幾個。

跟蹤記錄通過批注加以裝飾。批注是一些保存跟蹤記錄並被記錄進跟蹤數據庫的字符串。關聯活動和關聯工作流的跟蹤記錄有一個創建好的批注的集合,但你可以為用戶關聯事件的跟蹤記錄提供一個額外的批注。

在WF中跟蹤這一術語和平常“跟蹤”的概念沒有什麼不同。平常意義上的“跟蹤”是一個有用的調試工具,在ASP.NET、像WPF之類的.NET技術及Windows Forms中都支持跟蹤調試的能力。跟蹤允許你過濾跟蹤信息記錄以滿足你的需要,你既可只看異常的跟蹤信息,也能看到整個跟蹤棧。

WF跟蹤基於相似的概念,事實上是過濾。正如你可能想到的,關聯活動事件和關聯工作流事件將產生所有類型的跟蹤記錄,你或許能從中找到感興趣的記錄(如未處理的異常或空閒狀態),你可以決定其它的事件不用進行跟蹤。

為過濾掉你不想進行跟蹤的事件,你要創建一個跟蹤配置文件。一個跟蹤配置文件是一個XML文檔,它指明了跟蹤的對象和要排除跟蹤的對象。和跟蹤不同,跟蹤配置文件指明哪些東西要寫入跟蹤數據庫,而不是指明以後哪些東西能被查看到。假如你排除了一些事件,這些排除的事件就不會向數據庫裡寫任何東西。和跟蹤的另一個不同之處是,跟蹤配置文件的XML文檔也被記錄進跟蹤數據庫,當執行工作流時被恢復。換句話說,跟蹤記錄了指定的要去跟蹤的任何東西,但不進行跟蹤信息歸類。

設置SQL Server進行跟蹤

盡管你可創建自定義的跟蹤服務來把跟蹤數據記錄進各種存儲中(如消息隊列或數據文件),但本章,我們將把注意力放到SQL Server 2005數據庫上,WF有能力把事件數據記錄到SQL Server 2005數據庫中。WF為使用SQL Server 2005提供了內置的創建支持。

我們先在SQL Server Management Studio(或者Express版本)中創建一個新的數據庫。然後需運行一些由WinFX組件提供的SQL腳本,這些腳本將創建數據庫角色、表和視圖、必須的存儲過程以和你的工作流進行交互。我們就來通過創建一個新數據庫並運行一些准備好的腳本來開始吧,然後我們將使用WF跟蹤服務記錄下跟蹤數據並寫入數據庫。

備注:我在下面的步驟中使用SQL Server Express,但這些步驟對於其它版本的SQL Server 2005同樣適用。

創建一個SQL Server 2005跟蹤數據庫

1.啟動SQL Server Management Studio,連接數據庫引擎。

2.在數據庫節點上單擊右鍵激活右鍵快捷菜單,選擇“新數據庫”。

3.在新數據庫對話框中輸入“WorkflowTracking”作為數據庫的名稱字段,點擊確定。

4.下一步將執行WF為設置跟蹤所提供的腳本(這會創建表、視圖以及工作流跟蹤的角色)。這些腳本的位置在<%WINDIR%>\Microsoft.NET\Framework\3.0\Windows Workflow Foundation\SQL\ZH-CHS,在這裡<%WINDIR%>是指你的Windows目錄(通常是C:\Widows)。在SQL Server Management Studio打開Tracking_Schema.sql文件。

5.SQL Server Management Studio會在一個新窗口中導入文件中的腳本,但在我們運行腳本前,我們需指明在哪個數據庫中運行這些腳本,因此我們要選擇WorkflowTracking數據庫。

6.點擊工具欄上的執行按鈕執行這些腳本。

7.重復4-6步執行Tracking_Logic.sql腳本。這將在數據庫中創建必須的存儲過程。

我們現在就創建了一個將記錄跟蹤信息的數據庫,但怎樣得到已記錄的信息呢?什麼組件進行這方面的工作呢?讓我們看看!

使用SqlTrackingServer服務

在工作流跟蹤數據庫設置好後,現在就是實際使用它的時候了。我們先創建一個新的工作流並看看我們怎樣去跟蹤事件。我們將創建一個稍微復雜一些的工作流,裡面有幾個事件可以提供給我們去進行跟蹤。在我們創建一個原始的工作流後,我們將增加必要的跟蹤代碼。

創建一個新工作流並進行跟蹤

1.為更方便些,我已創建了兩個版本的樣例應用程序。Workflow包含兩個不同版本的應用程序:一個是不完全版本,一個是完全版本。完全版本已完全編寫完成並可直接運行,非完全版本可方便你進行修改,並按步驟完成相應練習。你可通過本章後面的下載鏈接下載這些項目文件。

2.下載本章源代碼,打開TrackedWorkflow解決方案,像第三章中相應步驟一樣創建一個順序工作流庫的項目,名稱為TrackedWorkflow。

3.在你完成以上步驟後,Visual Studio會打開工作流設計器以便進行編輯。

4.從工具箱中拖動一個IfElse活動到設計器界面上。如下圖:

5.單擊左邊的ifElseBranchActivity1分支,激活它的屬性使其在Visual Studio中的屬性窗口中顯示。

6.尋找 ifElseBranchActivity1 的 Condition 屬性。點擊下拉列表框上向下的箭頭打開下拉列表框,選擇其中的代碼條件節點。如下圖:

7.Condition 屬性現在會在它的左邊呈現出一個“+”號。單擊這個+號展開其屬性網格,這會暴露出Condition屬性的Condition名稱字段。在編輯框中,輸入QueryDelay。我們將使用這個方法來決定我們將執行IfElse活動的那個分支。

8.下一步我們在左邊的分支(這個分支在條件值為True時執行)添加一些活動。首先,從工具箱中拖拽一個Code活動到IfElse的左邊分支即ifElseBranchActivity1上。

9.你看到的驚歎號標記的意思在前面的章節我已描述過,意思是我們還有工作要做。在這裡,它指出我們需添加一個方法,Code活動添加到工作流中執行時將調用這個方法。在Visual Studio的屬性面板上,定位到 ExecuteCode 屬性,在該編輯框中輸入PreDelayMessage。

10.也許你要看看我要做什麼……其實就是添加一個延時工作流,在第三章我們已經創建過。就像在第三章做的一樣,再拖拽一個Delay活動和另一個Code活動進ifElseBranchActivity1中,然後設置它們的屬性。Delay活動延時10秒(00:00:10),第二個Code活動執行一個名稱為PostDelayMessage的方法。完成這些步驟後的設計器界面如下圖所示:

11.在設計器中的工作完成後,我們就來添加相應代碼。在解決方案資源管理器中的Workflow1.cs文件上單擊右鍵,選擇查看代碼。然後在項目中添加對System.Windows.Forms的引用,然後在Workflow1.cs文件的頂部聲明和其對應的下面的名稱空間。

using System.Windows.Forms;

12.你查看這個文件,你會看到Visual Studio為你添加的作為活動屬性的三個事件處理程序:PreDelayMessage、PostDelayMessage和QueryDelay。和第三章類似,在Code活動中添加消息對話框,以使應用程序能在工作流執行時通知你。對於PreDelayMessage,添加下面的代碼:

MessageBox.Show("Pre-delay code is being executed.");

對於PostDelayMessage,添加下面的代碼:

MessageBox.Show("Post-delay code is being executed.");

13.我們些許更感興趣的是在QueryDelay中添加的以下代碼:

e.Result = false; // 假定我們不延時
if (MessageBox.Show("Okay to execute delay in workflow processing?",
   "Query Delay",
   MessageBoxButtons.YesNo,
   MessageBoxIcon.Question) == DialogResult.Yes)
{
 // 需進行延時處理
 e.Result = true;
 // 顯示消息
 Console.WriteLine("Delay path taken");
} // if
else
{
 // 顯示消息
 Console.WriteLine("Delay path NOT taken");
} // else 

14.完成上述步驟後,我們需要為我們的WorkflowTracker主應用程序添加對工作流項目TrackedWorkflow的項目引用,步驟略。

15.在WorkflowTracker項目中打開Program.cs文件,查找下面的代碼:

Console.WriteLine("Waiting for workflow completion.");

16.為創建一個Workflow實例,在上述代碼下添加下面的代碼:

// 創建工作流實例。
WorkflowInstance instance =
 workflowRuntime.CreateWorkflow(typeof(TrackedWorkflow.Workflow1));
// 啟動工作流實例。
instance.Start();

17.編譯解決方案,糾正任何編譯錯誤。

18.按下F5(或Ctrl+F5)執行這個應用程序,你將看到以下控制台的輸出結果:

我們現在就有了一個基本的工作流,我們可使用它去體驗WF的跟蹤能力。我們現在就回去添加我們需要的代碼以執行跟蹤。

為我們的工作流添加SqlTrackingService

1.WF由活動和工作流事件跟蹤能力承載,因此我們不需為跟蹤事件做太多工作。盡管如此,我們仍然需在主程序文件中添加一些邏輯。首先,要為WorkflowTracker應用程序添加System.Configuration引用,我們需要它來把訪問數據庫的連接字符串存儲到應用程序的配置文件裡。

2.下一步,為WorkflowTracker應用程序添加一個應用程序配置文件。方法是在Visual Studio的解決方案管理器中的WorkflowTracker樹節點上單擊右鍵,依次選擇添加、新建項。在呈現的添加新項對話框中選擇應用程序配置文件,點擊確定。這就為我們的應用程序添加了一個新的app.config文件。參見下圖:

3.打開app.config文件,在Configuration的開始標記和結束標記間插入下面的內容:

<connectionStrings>
 <add name="TrackingDatabase" connectionString="Data Source=(local)\SQLEXPRESS;Initial Catalog=WorkflowTracking;Integrated Security=True;"/>
</connectionStrings>

備注:上面的連接字符串可能和你實際應用中有所不同,你需要靈活進行配置。

4.點擊WorkflowTracker項目中的WorkflowFactory.cs文件,查看其代碼。

5.在該文件中聲明以下名稱空間(需添加 System.Configuration 引用):

using System.Workflow.Runtime.Tracking;
    using System.Configuration;

6.在WorkflowFactory.cs文件中,找到我們創建WorkflowRuntime實例的地方,在這裡我們需要為WorkflowRuntime引入SqlTrackingService。在GetWorkflowRuntime方法中添加下面的代碼:

String conn = ConfigurationManager.ConnectionStrings["TrackingDatabase"].ConnectionString;
_workflowRuntime.AddService(new SqlTrackingService(conn)); 

完成了上述步驟,我們就添加了實際中要去執行跟蹤的代碼(稍後,我們會添加更多的代碼來顯示跟蹤結果)。編譯該解決方案,然後按F5或Ctrl+F5執行它。

備注:假如程序中出現 ArgumentException 異常,最可能的原因是運行時沒有訪問數據庫的權限。

假如工作流運行正常,你可在WorkflowTracking數據庫的ActivityInstance表中看到下圖5-1中顯示的結果。

圖5-1 表ActivityInstance中的記錄

檢索來自於工作流的跟蹤記錄

1.打開WorkflowTracker項目中的 Program.cs 文件。

2.在文件中聲明以下名稱空間:

using System.Configuration;
  using System.Workflow.Runtime.Tracking;

3.在Main方法中,找到下面的代碼:

waitHandle.WaitOne();

4.在上面的代碼下添加以下的的代碼:

ShowWorkflowTrackingEvents(instance.InstanceId);
  ShowActivityTrackingEvents(instance.InstanceId);

5.上面我們調用的一組方法並不存在,我們需要添加它們。在 Program 類中添加這些方法:

Code
// The activity tracking record display method
static void ShowActivityTrackingEvents(Guid instanceId)
{
  SqlTrackingQuery sqlTrackingQuery = new SqlTrackingQuery(ConfigurationManager.ConnectionStrings["TrackingDatabase"].ConnectionString);
  SqlTrackingWorkflowInstance sqlTrackingWorkflowInstance = null;
  sqlTrackingQuery.TryGetWorkflow(instanceId, out sqlTrackingWorkflowInstance);
  if (sqlTrackingWorkflowInstance != null)
  {
    Console.WriteLine("\nActivity Tracking Events:\n");
    Console.WriteLine(" Status :: Date/Time :: Qualified ID");
    foreach (ActivityTrackingRecord atr in sqlTrackingWorkflowInstance.ActivityEvents)
    {
      Console.WriteLine(" {0} :: {1} :: {2}", atr.ExecutionStatus, atr.EventDateTime, atr.QualifiedName);
    } // foreach
  } // if
}
// The workflow instance tracking record display method
static void ShowWorkflowTrackingEvents(Guid instanceId)
{
  SqlTrackingQuery sqlTrackingQuery = new SqlTrackingQuery(ConfigurationManager.ConnectionStrings["TrackingDatabase"].ConnectionString);
  SqlTrackingWorkflowInstance sqlTrackingWorkflowInstance = null;
  sqlTrackingQuery.TryGetWorkflow(instanceId, out sqlTrackingWorkflowInstance);
  if (sqlTrackingWorkflowInstance != null)
  {
    Console.WriteLine("\nWorkflow Instance Events:\n");
    Console.WriteLine(" Description :: Date/Time");
    foreach (WorkflowTrackingRecord workflowTrackingRecord in sqlTrackingWorkflowInstance.WorkflowEvents)
    {
      Console.WriteLine(" {0} :: {1}", workflowTrackingRecord.TrackingWorkflowEvent, workflowTrackingRecord.EventDateTime);
    } // foreach
  }
} 

在最後一步中忽然冒出大量的代碼,但實際上並不太復雜。我們首先創建了一個SqlTrackingQuery的實例,為它提供了我們曾提供給SqlTrackingService的相同的連接字符串。然後我們通過當前工作流實例的ID(一個Guid)標識,從數據庫中查詢該實例的跟蹤信息。該查詢由SqlTrackingService.TryGetWorkflow執行。假如數據庫中有我們指定的工作流的跟蹤信息,我們循環獲取跟蹤記錄(查詢返回給我們的是一個workflowTrackingRecord對象的集合),從中提取我們感興趣的信息。假如查詢結果中沒有記錄,也就沒有跟蹤信息寫到控制台窗口中。最終的屏幕的輸出結果如圖5-2所示(在調試模式下運行代碼的話,你或許需要設置一個斷點才能看到下圖的輸出結果)。

跟蹤用戶事件

SqlTrackingService是WF的一部分,它具有跟蹤事件的能力。也就是說,它能跟蹤活動和工作流激發的標准事件。但由你生成的事件呢?我們又如何跟蹤它們呢?

Activity活動支持一個名叫TrackData的方法,TrackData有兩個重載版本:一個版本接受一個要存儲進跟蹤數據庫中的對象,另一個版本接受一個字符串類型的鍵及一個要存儲進跟蹤數據庫中的對象。

假如你執行TrackData並為跟蹤傳入通常是字符串類型的數據,那這些信息將作為用戶事件數據存入跟蹤數據庫。

檢索來自你的工作流的跟蹤記錄

1.打開WorkflowTracker項目中的Workflow1.cs文件。

2.找到我們在創建工作流時添加的PreDelayMessage方法和PostDelayMessage方法。

3.在名為PreDelayMessage的方法內的顯示信息對話框的代碼下面添加以下代碼:

this.TrackData("Delay commencing");

4.同樣,在名為PostDelayMessage的方法內的顯示信息對話框的代碼下面添加以下代碼:

this.TrackData("Delay completed");

5.編譯並執行。

現在打開WorkflowTracking數據庫中的UserEvent表,裡面有兩行,我們在工作流中每調用TrackData一次就產生一條記錄,表中部分內容如圖5-3所示。

圖5-3 UserEvent表中顯示的調用TrackData的結果

創建自定義跟蹤配置文件

在本章我已談到過跟蹤配置文件,但當時並未詳細深入,在這節我將深入了解它的細節。

你可回憶一下,跟蹤配置文件用來限制WF跟蹤架構將存儲到跟蹤數據庫中的信息數量。跟蹤配置文件不僅僅是一個XML文檔,也用來規定一個給定的工作流的跟蹤將包含和排除的東西。但在代碼中完成這些事(比手動添加一個XML的跟蹤配置文件)更加容易。這裡有一個TrackingProfile對象及在表5-2中看到的其余對象可用,它們用來創建這個XML文檔。

有了這個TrackingProfile對象,你或許會自然的想到這也是一個有用的XML序列化器,可用來把TrackingProfile對象轉換成你需要的XML文檔並存入數據庫,事實上,這是TrackingProfileSerializer。WF並不內在支持把XML信息寫入數據庫,但你可使用類型化的ADO.NET技術及跟蹤數據庫中提供的存儲過程容易地來完成這一工作。

假如你回去看看表5-2,你會找到一些帶有“location”和“point”名稱的對象,它們分別和activity、workflow和user事件相對應。我們在這時談到“location”和“point”究竟意味著什麼呢?

在本章我已談到過跟蹤配置文件,但當時並未詳細深入,在這節我將深入了解它的細節。

其實,“location”指在你的工作流中活動、工作流或用戶相關的事件發生時的一個指定的位置。Locations描述了要跟蹤的事件。使用一個location對象,你可更精確地指定你想跟蹤及排除的的事件。

跟蹤points收集locations,它們能在你的工作流中的一個或多個地方觸發跟蹤信息。你可把跟蹤點當成一個感興趣的點來考慮。它能在你的工作流代碼中跨越不同的位置。在你為跟蹤點指定條件和位置後,在跟蹤時它視情況可能觸發也可能不觸發。

為什麼談及所有這些呢?因為當我們建立一個跟蹤配置文件時,你真正要做的工作是把跟蹤點和位置添加到profile對象中,以作為跟蹤事件的過濾器去使用。

創建一個新的跟蹤配置文件

1.打開WorkflowTracker項目中的Program.cs文件。

2.我們將加入的代碼並不一定就難於理解,只是它相當大。首先有必要聲明以下一些名稱空間:

using System.Workflow.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.IO;

3.上述步驟後,我們去找到Main方法。在該方法中創建工作流的代碼前添加以下代碼:

TrackingProfile profile = CreateProfile();
StoreProfile(profile, ConfigurationManager.ConnectionStrings["TrackingDatabase"].ConnectionString);

4.我們在上面的代碼中調用了兩個方法,我們還需要在Program類中添加它們。在Program類中添加CreateProfile方法的代碼如下:

CreateProfile方法

static TrackingProfile CreateProfile()
{
  // Create the basic profile
  TrackingProfile profile = new TrackingProfile();
  // Create the activity location, meaning the events we're interested in
  ActivityTrackingLocation actLoc = new ActivityTrackingLocation(typeof(Activity));
  actLoc.MatchDerivedTypes = true;
  actLoc.ExecutionStatusEvents.Add(ActivityExecutionStatus.Executing);
  // Create the activity track point and add the location we just created
  ActivityTrackPoint actPt = new ActivityTrackPoint();
  actPt.MatchingLocations.Add(actLoc);
  profile.ActivityTrackPoints.Add(actPt);
  // Create the workflow location
  WorkflowTrackingLocation wfLoc = new WorkflowTrackingLocation();
  wfLoc.Events.Add(TrackingWorkflowEvent.Started);
  wfLoc.Events.Add(TrackingWorkflowEvent.Idle);
  // Create the workflow track point
  WorkflowTrackPoint wfPt = new WorkflowTrackPoint();
  wfPt.MatchingLocation = wfLoc;
  profile.WorkflowTrackPoints.Add(wfPt);
  // Set the version of the profilethis version must not already exist
  // in the database.
  profile.Version = new Version("1.0.0.0");
  return profile;
}

5.同樣,添加StoreProfile方法:

StoreProfile方法

static void StoreProfile(TrackingProfile profile, string connString)
{
  // First, serialize the profile into an XML string
  TrackingProfileSerializer serializer = new TrackingProfileSerializer();
  StringWriter writer = new StringWriter(new StringBuilder(), CultureInfo.InvariantCulture);
  serializer.Serialize(writer, profile);
  // Then, write the XML string to the database
  SqlConnection conn = null;
  try
  {
    if (!String.IsNullOrEmpty(connString))
    {
      // Create a connection object
      conn = new SqlConnection(connString);
      // Create a dummy for the stored proc name
      string storedProc = "dbo.UpdateTrackingProfile";
      // Create the command
      SqlCommand cmd = new SqlCommand(storedProc, conn);
      cmd.CommandType = CommandType.StoredProcedure;
      // Add the parameters
      SqlParameter parm = new SqlParameter("@TypeFullName", SqlDbType.NVarChar, 128);
      parm.Direction = ParameterDirection.Input;
      parm.Value = typeof(TrackedWorkflow.Workflow1).ToString();
      cmd.Parameters.Add(parm);
      parm = new SqlParameter("@AssemblyFullName", SqlDbType.NVarChar, 256);
      parm.Direction = ParameterDirection.Input;
      parm.Value = typeof(TrackedWorkflow.Workflow1).Assembly.FullName;
      cmd.Parameters.Add(parm);
      parm = new SqlParameter("@Version", SqlDbType.VarChar, 32);
      parm.Direction = ParameterDirection.Input;
      parm.Value = "1.0.0.0";
      cmd.Parameters.Add(parm);
      parm = new SqlParameter("@TrackingProfileXml", SqlDbType.NText);
      parm.Direction = ParameterDirection.Input;
      parm.Value = writer.ToString();
      cmd.Parameters.Add(parm);
      // Open the connection
      conn.Open();
      // Write the XML data
      cmd.ExecuteNonQuery();
    } // if
  } // try
  catch (Exception ex)
  {
    // If the exception is telling us we've already written
    // this profile to the database, just pop up an informational
    // message.
    if (ex is SqlException)
    {
      // Check to see if it's a version error
      if (ex.Message.Substring(0,24) == "A version already exists")
      {
        // Version already exists
        Console.WriteLine("NOTE: a profile with the same version already exists in the database.");
      } // if
      else
      {
        // Write error message
        Console.WriteLine("Error writing profile to database: {0}", ex.ToString());
      } // else
    } // if
    else
    {
      // Write error message
      Console.WriteLine("Error writing profile to database: {0}", ex.ToString());
    } // else
  } // catch
  finally
  {
    // Close the connection
    if (conn != null)
    {
      conn.Close();
    } // if
  } // finally
}

6.假如你在現在執行本程序,CreateProfile方法會創建的配置文件並把它寫入數據庫。假如你再仔細地看看步驟4中的代碼,你會注意到僅僅只跟蹤了很少數的活動事件和工作流事件。因此,你可能會期望在工作台窗口中將由ShowActivityTrackingEvents和ShowWorkflowTrackingEvents輸出很少的幾行信息,但實際上,正確的結果如下圖5-4(可把它和圖5-2比較)。

圖5-4 WorkflowTracker跟蹤數據的屏幕輸出結果

CreateProfile方法創建了一個新的TrackingProfile並添加了一個活動跟蹤點和工作流跟蹤點。每個跟蹤點都有一個單一的跟蹤位置,它定義了要跟蹤哪些事件,因此我們只能看到來自活動的Executing事件和來自工作流實例的Started事件和Idle事件。

而StoreProfile方法,它把跟蹤配置文件序列化成XML形式,然後用典型的ADO.NET技術把這個XML存入跟蹤數據庫。試圖更新一個跟蹤配置文件的同一版本會被認為是一種錯誤,因此會拋出一個異常。

用WorkflowMonitor查看跟蹤信息

假如有人想出一個現成的用來監測工作流事件的工具那不是很好?就像我們本章前面一樣,能把跟蹤記錄輸出是很棒的事,但用一個好的圖形用戶界面來做這個工作將是更加棒的一件事。事實上,我們是幸運的!當我們加載WF時,你也可加載了一套示例,裡面包含的是一個叫做WorkflowMonitor的應用程序。在這裡我們需要去做的是編譯這個應用程序。

編譯WorkflowMonitor

1.WorkflowMonitor是工作流示例庫的一部分,它由Windows SDK承載。把WFSample.zip文件復制到本章解決方案的目錄下並進行解壓。WFSamples.zip文件在下面的位置可找到(聲明:本人未在下面的目錄找到該文件,但從微軟官方網站上可進行下載,本章的源代碼中也提供有WorkflowMonitor的源代碼):

C:\Program Files\Microsoft SDKs\Windows\v6.0\Samples\WFSamples.zip

2.在Visual Studio中打開WorkflowMonitor.sln文件。

3.編譯並生成該應用程序。

這個應用程序編譯時沒有錯誤,然後你卻不能執行它。當SqlTrackingService把跟蹤記錄寫進跟蹤數據庫時,工作流對象的數據類型就是記錄的一批信息中的一條。假如支持你的工作流的類型沒有在全局Assembly Cache中,WorkflowMonitor就不能在視圖設計器中加載你的工作流對象。因此,對於TrackedWorkflow來說,你必須把你的工作流組件放到全局Assembly Cache中或者把TrackedWorkflow中的DLL文件放到和WorkflowMonitor的可執行文件(即WorkflowMonitor.exe)的相同的目錄下。在本例中,更容易的方法是復制WorkflowMonitor.exe文件到我們的工作流的可執行代碼的相同目錄下。

執行WorkflowMonitor

1.復制WorkflowMonitor.exe可執行文件到WorkflowTracker解決方案目錄中的bin\Debug子目錄下(在此生成的是調試版本的應用程序)。

2.雙擊WorkflowMonitor.exe文件執行該應用程序。

3.WorkflowMonitor把配置信息存儲在WorkflowMonitor.config配置文件中,可在“Application.LocalUserAppDataPath”找到。(假如你正運行SQL Server Express,當簡單地單擊確定,在WorkflowMonitor試圖連接該數據庫時你可能會看到一條錯誤信息。)因為這可能是在你的系統上運行WorkflowMonitor的第一時間,配置文件還未存在。WorkflowMonitor已考慮這些並立即顯示一個設置對話框。如下圖所示:

4.你可通過這個設置來修改跟蹤數據庫所在的主機名、跟蹤數據庫名、輪詢周期(默認是5秒)等。現在,我們真正要做的是設置服務器的名稱和數據庫的名稱,在你輸入這些值後點擊確定。

5.然後WorkflowMonitor監控器建立一個工作數據庫的鏈接,並讀出找到的跟蹤記錄。假如記錄中有類型信息,它將在設計器中顯示找到的工作流。在本例中,唯一能找到的工作流是TrackedWorkflow,但在你創建的工作流越多,顯示的也將越多。WorkflowMonitor程序的用戶界面如下圖所示:

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved