目錄
開發現狀
開發問題
解決方案
1)自定義UserFunction
2)預調用服務
預調用服務方案設計與實作
代碼設計
實作結果
開發現狀
Camstar開發過程中,業務代碼通常寫在以下位置:
1)Web服務端(C#代碼)
基于.NET的B/S架構,代碼運作環境是IIS,因為直接使用Visual Studio即可程式設計,并且友善和UI做代碼互動,是以很多業務代碼都在此處編寫。
2)Designer的CLF中
由Web服務端代碼調用Camstar的WCF服務觸發,在designer中,CLF代碼全部執行完畢後才會調用Commit方法送出事務,寫入資料庫,如果發生異常則會復原全部CLF代碼,是以對于事務要求較高的業務代碼,通常在Designer中編寫。
開發問題
但是最近遇到需求,業務代碼難以在designer的CLF中編寫,并且又需要對事務做把控。于是産生問題:如何在C#代碼中控制整個程式的事務。
解決方案
1)自定義UserFunction
該方案的開發過程主要是先編寫C#代碼自定義userfunction,然後将編譯好的dll注入到Camstar中,之後在designer的clf中就可以調用到該userfunction。由于代碼實際上是在Camstar Service中運作,是以可以保證事務。但是這種開發方式,目前似乎沒有項目這麼做過,其中的難度較大,光是可以預料到的問題點就使我不想使用該方案。該方法在西門子官網有教程文檔,我也沒具體做過,是以本文不具體實作該方案。
2)預調用服務
研究Camstar的Event,如下圖所示,Event使用了模闆方法模式設計,是以可以清晰地看出整個designer程式中的代碼運作生命周期(黃色閃電方法從上往下依次執行)。

執行到AfterCommit的時候,已經送出到資料庫了。那麼如果能把Commit代碼的觸發交給C#代碼中控制,那麼既可做到由C#代碼控制整個程式的事務送出。模闆方法模式+反向控制,我很自然地就想到了通過鈎子方法來實作。(模闆方法模式和鈎子方法可以參考我以前的博文:模闆方法模式學習總結)
預調用服務方案設計與實作
文章中我不友善把具體代碼之類的都傳上來(我部落格中一直是不上傳具體産品代碼的),設計思路和結果都有了,我相信懂的人自然知道怎麼代碼該怎麼寫。
代碼設計
關鍵思路是如何在代碼執行送出時停止/中斷。由C#代碼發出送出指令。
我采用的方法是中斷,中斷的方法是在Commit代碼之前通過異常的方式強行中斷(應該還有其他更恰當的方式)。
Service基類定義勾子變量 xxxInterrupt,bool類型,用于反向控制是否中斷。
在Commit之前寫入CLF代碼,if(xxxInterrupt) throw; 。将執行結果一并抛出。
C#代碼中,由于bool預設值為false,是以對原有代碼無影響。如果需要中斷,則傳入參數Service.xxxInterrupt = true;
實作結果
自定義一個Lot建立界面,定義倆個按鈕PreCommit和RealCommit分别代表預送出(不送出到資料庫)和真實送出(送出到資料庫)。頁面定義一個文本框顯示執行結果(友善測試),整體頁面如下圖1所示。
(圖1)
服務端調用Lot建立接口,根據給定的流水号規則建立Lot。由于流水号建立不重複,如果PreCommit和RealCommit都執行完成後,系統隻真實往資料庫送出一次修改,則說明該方案實作成功。
操作1:點選PreCommit,操作結果中顯示未送出一筆資料。
操作截圖:
(圖2,第一次點選,預送出PEP100014,執行完後查資料庫無新資料)
操作2:點選3次RealCommit,操作結果中顯示成功3筆資料,其中第一筆為操作1中的資料。
(圖3,第一次點選,送出PEP100014)
(圖4,第二次點選,送出PEP100015,直接寫資料庫)
(第三次點選,送出PEP100016,直接寫資料庫)
如果隻點選PreCommit,不點選RealCommit,最終資料庫未插入任何資料,方案實作成功。