本文章是由機器翻譯。

地基

版本控制工作流程

Matthew Milner

可從 MSDN 程式庫 的程式碼下載
瀏覽線上的程式碼

內容

問題
.NET 版本
XOML 工作流程定義與版本控制
活動的版本控制
版本控制工作流程服務
動態更新

在任何的應用程式中,沒有一件事,您可以確定的: 變更發生。其中一個最常見的問題,我發現使用 struggling 的開發人員會是如何處理版本控制工作流程和其相關的類別。在本月的專欄中,我將討論相關工作流程的版本控制,核心問題,並提供我的建議變更工作流程定義、 活動及工作流程服務。

fig01.gif

[圖 1 的可能會保存簡單的工作流程

如果您在建置.NET 應用程式目前 — 說,Windows Presentation Foundation (WPF) 或 ASP.NET 應用程式 — 您可能會想到版本,或您不可能。要部署至 ASP.NET 應用程式的更新時您通常妥處理程序,只要將複製透過所有 (或某些元件,包括頁面、 二進位碼檔案和組態。在某些的情況下您可能會對此部署的疑慮,例如,確定沒有要求目前正在執行,但這個處理序通常可管理。如此,原因部署新版本的如此困難的工作流程應用程式嗎?

工作流程,可讓您長時間執行商務處理序或商務邏輯的模型。此外,Windows Workflow Foundation (WF) 會提供持續性服務,讓商務程序的個別的執行個體的狀態儲存至長期儲存區例如 Microsoft SQL Server 資料庫。儲存狀態會由序列化的.NET 物件,組成,和其中位於問題。

請考慮使用某些.NET 型別,做為 [資料工作流程,說的順序類別。工作流程被開始的傳入中,做為接著被保存 (Persist 資料庫包含序列化的順序物件其狀態) 參數的順序物件。現在變更順序的物件類別,並重建您的應用程式程式庫。時,會保存工作流程需要繼續,因為延遲已過期,或向工作流程引發某些事件,Order 物件需要還原序列化。不幸的是,因為該型別已變更,在還原序列化失敗,擲回例外狀況。

某些變更會造成還原序列化 (Deserialization) 的問題,因為標準的.NET 二進位序列化失敗,因 WF 實作序列化 (Serialization) 的其他問題發生。不論在的原因最終結果是相同: 當您嘗試載入參考型別,已變更的工作流程的例外狀況。這些型別可能類別或介面,您所建立,或它們可能是您所撰寫的自訂活動。

提供一個具體的範例,請考慮 [圖 1 ] 中的工作流程。它只會將某些資料寫入使用自訂 WriteLine 活動、 延遲 (也可讓它保存 (Persist),和寫入主控台主控台的詳細資料。

如果我啟動這項工作流程的執行個體,讓它執行閒置點,現在 — 延遲 — 它會保存在資料庫中。我可以關閉執行階段,並在我的版本 1.1 的工作流程上開始工作。我只會加入至工作流程定義將詳細資料寫入至主的控台,如 [圖 2 ] 所示的結尾的活動。

不啟動另一個工作流程執行個體的情況下,執行階段啟動,會造成持續性服務輪詢尋找過期的計時器的資料庫。當它找到現有的執行個體時,持續性服務會將嘗試載入物件,並將會得到例外狀況。我可以註冊在 WorkflowRuntime ServicesExceptionNotHandled 事件的事件處理常式,以偵測這項錯誤。我會看到的是持續性服務會引發事件的例外狀況訊息 「 陣列的界限之外未索引 」。

fig02.gif

[圖 2 修改工作流程定義

以下問題是,我已變更我的工作流程型別的定義,它不再符合已保存的工作流程時所存在的定義。當嘗試還原序列化工作流程的持續性服務時,我收到例外狀況,因為新的型別定義中包含執行個體已序列化時,不存在的欄位。讀取新的型別欄位並嘗試從序列化資料載入這些值還原序列化 (Deserialization) 的程式碼。因為執行個體已序列化時,某些欄位不存在時嘗試存取的資料,,會引發例外狀況。

.NET 版本

一個解決版本問題就是要利用內建於.NET Framework 的版本控制系統。自.NET Framework 1.0 版中,組件的版本會有被支援,而且是唯一的方式,來啟用組件的多個版本的並存支援中。簡,每個組件都可以有附加到其版本號碼,而組件的多個版本的組件使用金鑰簽署的時, 可以部署到全域組件快取 (GAC)。如在組件的版本和強式命名組件需詳細請參閱在組件上的 MSDN 文件.

這可讓您使用 1.0 版本的專案中建置您的工作流程和活動,、 簽署它們,並部署至 GAC。現在,您開啟一個工作流程時它持續存在,版本資訊就會是序列化狀態的一部分。如果您變更工作流程時,變更組件的版本很重要,而任何其他組件,工作流程定如果那些已變更,太。例如,如果您必須從先前的範例工作流程,且您變更 WriteLine 活動和工作流程定義,然後您必須遞增版本號碼每個專案中,和至 GAC 中部署更新程式。

這時候您會同時擁有 1.0 版和 1.1 版部署至 GAC 的工作流程。當版本 1.0 的工作流程從保存存放區載入時,執行階段將能夠解決版本 1.0 型別定義,並在還原序列化工作流程時,請使用該的型別資訊。因為執行階段可以找到定義) 的版本 1.1 的型別太,可以使用任何版本 1.1 工作流程,也保存。基本上,只要包含工作流程及其相關的類別的型別的組件可以解決,並且符合原始定義,工作流程會正確地還原序列,並可以繼續處理。您可以看到此程序在 圖 3 其中不同的版本從在的資料庫中載入,而其型別正確解析的運作方式當位於 GAC。

fig03.gif

[圖 3 並排的.NET 版本

一個重點来注意會是時,版本 1.0 的工作流程將會繼續使用,並處理,但它們仍然根據 1.0 版定義的工作流程。這表示您的工作流程 1.1 版中所引入的任何變更將不可以出現在工作流程定義。也就是任何活動,您加入、 移除,或否則變更不會出現在工作流程定義,且您將不會在看到這些變更,在版本 1.0 的工作流程的影響。稍後,我將討論這個功能稱為動態更新,提供能夠變更現有、 同處理序的 1.0 版工作流程。

只要有工作流程和相關的組件的並存的版本,並不代表的動作復原以及剛好,但是。您主應用程式是有可能建置應用程式資料的特定和可能最近、 在工作流程的版本,讓它可以與它們的方式互動。這可能會在嘗試與互動保存相關的類別的 1.0 版所建置的版本 1.0 工作流程時,主應用程式針對版本 1.1 工作流程的建置會遇到問題,造成問題。

一個的區域,這個問題通常出現為開發人員會是 ExternalDataExchangeService 與 HandleExternalEvent 和 CallExternalMethod 活動搭配使用本機通訊時。許多人,想它們的版本控制,做正確的事請遵循前一個步驟,以便 1.0 和 1.1 的版本可用。不過,主應用程式會嘗試傳送資料至工作流程透過事件時, 不再使用,介面型別比對。針對版本 1.0 建置工作流程執行個體時,主應用程式使用介面,版本 1.1。

完全瞭解為何這是一個問題,恢復通訊真的如何 WF 中。(請參閱更多的工作流程通訊,2007 年 9 月期,以的基礎.) HandleExternalEvent 活動建立佇列以接收資料,並該佇列的名稱包含介面的型別資訊]。當從主應用程式傳送資料時,它必須傳送至正確的佇列。ExternalDataExchangeService (EDS) 會使用型別資訊和事件名稱,來建立它認為是適當的佇列名稱。不幸的是,因為佇列依據介面的 1.0 版所建立,而且在 EDS 正在建立版本 1.1 為基礎的佇列名稱不符合兩個 IComparable 物件,將,和會找不到佇列。

若要暫時略過這個問題完全主機應用程式必須引發事件,在 1.0 版的介面上。兩個可能方法完成這項作業會包括反映 (Reflection) 和繼承。第一個選項會包括載入您的本機服務的原始版本中,並將它,以加入,EDS 後, 引發事件,在該介面,使用反映 (Reflection) 來重新中使用反映 (Reflection)。

第二個選項,包括建立新的組件,您建立介面的 [版本 1.1,並可讓您無法變更基底型別時,事件加入衍生型別,讓它從 1.0 版的介面,衍生。這的種方式在如果您提高 1.0 版介面的上已定義的事件,則取得建立正確的佇列名稱,將會,和訊息傳遞,即使您叫用在衍生的型別的作業。金鑰是介面的部署及變更,必須保留 1.0 版必須從 1.0 版介面衍生您的新介面及服務。[圖 4 ] 顯示這種方法。

fig04.gif

[圖 4 衍生本機通訊的介面

請注意只有衍生的服務和介面加入至,EDS。這可讓主應用程式與單一的服務互動,但會引發事件,根據多個介面。目標是要保留 1.0 版介面,並在使用中,所以,EDS 會建立符合,工作流程會建立的佇列名稱。也請注意這包括建立新專案,而不是只建立新的通訊程式庫版本。untenable 是文字,注意到當您想使用此方法的長文字。

通常,我的建議解決通訊是非常有鑑於此,避免本機通訊活動,並使用自訂的活動建立佇列根據簡單的名稱,例如移除大部分的工作流程和主機之間,型別相依性的字串。其他建議,是使用工作流程服務,提供接收要求和路由它們在的工作流程的正確版本的其他功能,如我稍後會討論。

XOML 工作流程定義與版本控制

讓生活更容易版本時,第一個步驟是使用 XOML-為基礎的工作流程,不需要編譯它們。這種真正的宣告式模型會提供許多好處,除了版本。2008 年的 MSDN Magazine 如需詳細資訊,請參閱 (」載入 WF 工作流程的模型").我會著重於優點的版本控制這裡。

建置工作流程,以程式碼的方法透過時, 您正在定義新的型別。例如,如果您建立新的程式碼使用 Visual Studio 專案或項目範本的工作流程時,您定義新類別衍生自 WF 組件中的型別。這是因為當您變更工作流程,藉由加入或移除活動時, 您會變更型別先前所述問題的主要原因。這不會發生在建置 XOML 工作流程時。

XOML 工作流程未編譯的會是只描述現有的型別的集合的 XML 文件。看起來這可能像有微妙的不同,但描述現有型別,而非建立新的型別會大的差異。

以下是一個 XOML 工作流程定義:

<SequentialWorkflowActivity x:Name="Workflow2" 
    xmlns:ns0="clr-namespace:SimpleWorkflows" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
  <ns0:WriteLineActivity x:Name="Hello" OutputText="Hello" />
  <DelayActivity TimeoutDuration="00:00:03" x:Name="SmallDelay" />
  <ns0:WriteLineActivity x:Name="World" OutputText="World" />
</SequentialWorkflowActivity>

您會看到根項目是在 System.Workflow.activities 組件中定義的 SequentialWorkflowActivity。這個型別會是版本為 3.0 中,和 nonchanging。如果您在建置使用此型別為您的根活動的工作流程工作流程是序列化,並保存,您可以確定,載入和還原序列化工作流程時,Runtime 將能夠找到 [SequentialWorkflowActivity 3.0 版在 GAC 中。

藉由加入或移除活動,呢變更工作流程定義?XOML 工作流程定義中, 您要直接變更某些不會變更任何型別的 XML。即使您變更工作流程定義中的根項目為其他型別時,您不變更現有的工作流程執行個體所需要的型別。事實,一旦從 [XOML 建立工作流程,該 XOML 會不由參考再次執行階段的執行個體的存留期。

使用 XOML-為基礎的工作流程表示您不需要版本您的工作流程因為您未定義型別。因為您沒有強式名稱和版本您的工作流程您還沒有強式名稱,而且版本在其他類型,例如本機通訊的介面和商業實體。會比較更容易進行不分行的變更例如型別而不需要多動作,在應用程式中加入成員或方法。

使用 XOML 工作流程缺點是,您可以小到沒有存取程式碼以外,什麼封裝在您的活動讓您得到撰寫更多的活動。但由於活動都是直接類別,這不是主要的封鎖程式,並可讓您擷取方法,可以使用提供的事件處理邏輯或檢查 XOML 工作流程中的活動的條件。

此外,因為 SequentialWorkflowActivity 類別沒有使用您在其上定義的商務任何的案例屬性,您將無法將參數傳遞至 CreateWorkflow 方法。幸運的是,您可以建立您自己的根活動輸入衍生自其中包含工作流程類型,並新增有,您所需的屬性,或您可以在初始的資料傳送後啟動的工作流程,以在接收活動] 或 [自訂活動開始您的工作流程。

以 XAML 為基礎的完整宣告式工作流程最後,轉寄查詢是在主要的模型選擇,傳入 WF 4.0。所許多增強功能都會包括哪些目前呼叫的 ActivityAction 時,取代事件的功能套用。基本上,這些將會提供您方法和模式使用活動的委派,有活動來執行這些活動,而不是叫用委派。

活動的版本控制

工作流程是活動,讓它後面所討論問題的許多到目前為止的工作流程型別套用活動型別。事實上,就像在工作流程類型會造成問題如果您將活動,如果您加入的活動的屬性型別,和執行不是版本,該活動的組件時,您會收到例外狀況,工作流程的還原序列化時。不幸的是,活動必須為類別,而且是有沒有簡單的 XOML 解決方案與工作流程必須已編譯的型別。

在簡短的答案,活動的是您應該版本使用.NET 版本技術,當您變更活動以任何方式使用介面。這可讓現有的工作流程和參考正確的版本] 和 [正確的執行新的工作流程。請記住,但是,如果您在方法內不會變更介面的活動中,以修正缺失,您可以讓此修正程式並部署組件具有相同的版本號碼。當載入和現有或新的工作流程所執行的活動時,便會執行正確的程式碼。

長的回應會包含序列化 (Serialization) 機制,.NET Framework,已超出本文的範圍中,深入瞭解。但是有兩個金鑰件事,我可以共用,可能會提供大部份的優點,以最低量的投資。

第一次,如果您將屬性或欄位加入至您的活動中,您可以標記以 NonSerialized 屬性,以避免出的界限的例外狀況時的工作流程建置針對先前的版本,您的活動的還原序列化索引欄位。

第二個,您可以覆寫 OnActivityExecutionContextLoad) 方法,以初始化任何還原序列時無法自動化的狀態。當從持續性狀態重新建立活動或新的執行內容建立的取得呼叫這個方法。這兩種技巧一起可協助您進行變更而不需要您強式名稱加以命名並變更版本號碼的活動。

版本控制工作流程服務

工作流程服務會提供本機通訊,以及其他機會 decoupling 來自工作流程的類似的問題。因為使用服務合約,建置工作流程服務的服務或資料的任何版本控制會協定工作流程將會需要重新建置針對 「 合約 」 的新版本的方法。當訊息到達一個服務端點時,它將接收由服務使用在協定中有一個特定的版本。如果郵件所適用的工作流程建置針對相同的版本,合約的則動作運作也。不過,如果工作流程已建立對舊版的合約,且接著被保存 (Persist),再在無法傳遞郵件。若要支援兩個版本,合約,您要部署服務的兩個版本。

正在不幸的您無法利用完整,Windows Communication Foundation (WCF),會讓新版本的服務來處理從舊的版本所建置的用戶端的訊息中固有的版本控制功能時 WCF 就不會提供機制來管理這種情況。在 WCF 程度請用戶端和服務只會交換訊息,然後.NET 型別無法執行跨網路]。我說相關的版本控制問題完全在.NET 層級並從用戶端使用訊息路由器就可以隱藏。

與工作流程服務好處是,則可以發佈兩個服務並排,使用不同的端點位址,尚未發行,讓在相同的位址的可存取這兩個服務的外貌。當您部署您的服務 1.0 版時,請採用此的方法,您可以部署它通過 WCF 路由器,只要在郵件中所會,並將它們傳送到服務上後方。當您準備好部署版本 1.1 的服務,您可以在版本 1.0 服務,或是 1.1 版服務根據訊息或它所接收的內容傳送訊息,取得更新路由的資訊。[圖 5 ] 顯示這個路由器概念,與路由器和用戶端與它們互動服務的兩個版本。

fig06.gif

[圖 5 使用路由器的版本控制服務

確保解決方案與路由器會使用在於將它部署與服務的 1.0 版。然後時移到下一版路由器不項目新增您將加入至部署並測試程序。.NET Framework 3.5 SDK 提供的範例路由器,並在您也可以依照資料有關使用 WF 規則進行路由決策的實際操作文件 .

動態更新

有關如何最佳管理變更工作流程的定義,並將新的和舊的版本,執行並存-處理所有討論之後, 沒有通常如何處理這些舊的工作流程的相關問題。您變更您的工作流程的。可能是它在邏輯中, 修正缺失或可能,您必須是所需的遵循法規。任何原因,通常是大小寫,讓現有的工作流程完成它們所定義的所有 tenable 的結果。在這些的情況下您可以考慮利用 WF 中的強大的功能: 動態更新。

簡言之,動態更新可讓您執行的工作流程執行個體中進行變更。這些變更可以由加入或移除工作流程結構的活動所組成。就是所有以您可以執行,但可以完全變更您的工作流程的定義。舉例來說,在狀態機器,您可以將整個狀態,這些接聽的事件,以及定義,轉換。您可以移除並 re-adding SetState 活動,來變更狀態轉換。在循序的工作流程中的,您可以新增或移除您的商務程序變更的步驟。

若要變更工作流程,您首先需要建立一個 WorkflowChanges 物件,根據工作流程。在該點 WorkflowChanges 物件會提供工作流程結構,您可以透過其 TransientWorkflow 屬性來操作複製的品。您可以複製品 (Clone) 來進行變更,藉由加入並移除活動。您所做的變更完成時您呼叫 ApplyChanges 方法 WorkflowInstance 類別上, 傳遞 WorkflowChanges,以表示您要套用至實際執行個體,的變更。

以下是範例稍早所示的工作流程,其中包含兩個 WriteLine 活動,以一個加入至序列的結尾的其他 WriteLine 活動的延遲活動。這個程式碼會執行工作流程閒置時,或延遲開始執行時。

WorkflowChanges changes = 
  new WorkflowChanges(instance.GetWorkflowDefinition());
CompositeActivity root = changes.TransientWorkflow;
WriteLineActivity wl = new WriteLineActivity {
  Name = "newWriteLine",
  OutputText = "dynamically added"
};
root.Activities.Add(wl);
instance.ApplyWorkflowChanges(changes);

這個簡單範例將示範是可能的但是更進階的案例可以建置許多的不同變更套用到執行中的工作流程。 這可讓您版本 1.0 的工作流程已啟動,變更執行個體,讓它的運作方式更喜歡在 version1.1 工作流程。

您問題或意見寄至 mmnet30@Microsoft.com.

Matt Milner 會是的 Pluralsight,他會著重在連線的系統技術 (例如: WCF、 Windows WF、 BizTalk、 」 都柏林及.Azure 服務的平台),技術人員的成員。 Matt 也是一個獨立的顧問,專精於 Microsoft.NET 應用程式設計和開發。 Matt 定期共用技術他的愛說在本機的地區,和國際會議,例如 Tech Ed。 Microsoft 已為他的社群解決連線系統的技術的貢獻,辨識 Matt 為的 MVP。 透過他的部落格,在連絡 Matt pluralsight.com/community/blogs/Matt.