天天看點

Winform開發架構之存儲過程的支援--存儲過程的實作和演化提煉(2)

我們整個執行個體是以一個客戶表T_Customer為例進行講解的,整個表的架構支援代碼,可以通過代碼生成工具進行快速生成,生成後包括了IDAL、Entity、DALSQL、BLL層代碼,然後可以利用代碼進行測試存儲過程是否執行成功等功能。

資料通路層的定義,依照架構的分層模式來處理,後面我們在增加DALOracle對Oracle資料庫進行支援即可。

生成後資料通路層接口,他們通過基類接口繼承的方式,已經具有了正常的增删改查、分頁等系列接口,但是其他業務接口還是需要自己定義的,如資料通路接口成的定義如下所示。

這裡面的代碼很簡單,沒有多餘的代碼行,那麼裡面究竟發生了什麼呢,其中的IBaseDAL又是什麼定義呢?

Winform開發架構之存儲過程的支援--存儲過程的實作和演化提煉(2)

其實,IBaseDAL就是定義了很多我們開發用到的基礎接口,如标準的增删改查,以及衍生出來的一些其他接口,如分頁查詢,條件查詢等接口内容。這個ICustomer就是用來定義一些除了标準接口不能實作外的業務接口。

如果我們需要實作基于存儲過程的接口,我們可能就需要增加一些接口定義,如下所示。

對于插入、更新和删除這樣的操作,我們隻需要傳回它是否成功就可以了,那麼它的接口實作應該是如何的呢?

由于我們的Winform開發架構底層是利用微軟企業庫EnterpriseLibrary來通路資料的,那麼對應這個企業庫的使用存儲過程的方法,也就是我們的實作了。

下面的代碼就是它們對應的SqlServer實作了。

對于有傳回輸出參數的值,我們的做法有些不同,不過最主要的還是最終擷取它的輸出參數值而已,代碼如下所示。

上面的代碼,主要就是利用了AddOutParameter對輸出參數的資訊進行設定,輸出參數的資料類型要和腳本裡面的類型定義對應,它的AddOutParameter的size參數值,可以為0。

最後我們通過db.GetParameterValue(command, "@MaxAge")的方式擷取它的輸出參數的值,并傳回即可。

最後一個例子是介紹如何通過代碼調用,獲得它的實體對象或者實體對象清單,以及DataTable集合對象的例子了,這個也相對不是很麻煩,參照架構裡面的做法即可。

擷取實體對象資訊的代碼如下所示。

擷取集合的代碼如下所示。

上面是基于SqlServer存儲過程的調用,前面的一篇文章我們介紹了存儲過程的Oracle定義,是增加了一個遊标來進行記錄行資料的處理的,不管對于單行記錄,還是多行記錄,都是用了遊标的輸出參數的,那麼在用戶端裡面,使用EnterpriseLibrary,應該如何調用,并且不需要傳入這個輸出參數的呢,做法其實很類似,隻是有一點差異而已。

我們先從最簡單的Oracle存儲過程調用案例開始,介紹如何調用插入、更新和删除操作的Oracle存儲過程的調用。這裡和SqlServer的類似,不同的是我們使用了p_字首來定義參數(基于Oracle的通用腳本參數定義規則)。

Oracle輸出外部參數的做法也和sqlServer類似,具體調用代碼如下所示。

其他的也就很類似,就不再一一贅述了,基本上和SqlServer的一緻,我們節省篇幅,用來看看如何調用傳回記錄的查詢接口。下面是對應的Oracle存儲過程的調用代碼

傳回多條記錄的操作代碼如下所示。

看完上面兩個對記錄處理的接口,我們看到,還是對我們在Oracle存儲過程裡面定義的輸出遊标參數忽略處理,我們不需要對它進行傳值,它好像是透明的,呵呵。

這樣它的做法就和SqlServer個各個接口實作也都差不多的了。

下面的腳本是我們之前定義的Oracle存儲過程腳本,友善對比參照一下調用的函數代碼。

上面我們定義了資料通路接口,以及兩種資料實作層,在架構裡面會根據不同的資料庫類型配置,然後從不同的資料庫通路層建構對象的,業務邏輯層主要就是對他們的接口進行調用了,具體代碼如下所示。

為了驗證我們的實作是否能夠正常處理,并順利擷取對應的對象或者集合,我們需要編寫一些代碼,用來對它進行測試。

測試的代碼如下所示。

為了對他們進行測試,我們需要分别對SqlServer和Oracle進行測試,然後才能确認我們的實作是正确的。

分别在SQLServer和Oracle上運作存儲過程腳本,建立對應的資料庫腳本,如下所示。

Winform開發架構之存儲過程的支援--存儲過程的實作和演化提煉(2)
Winform開發架構之存儲過程的支援--存儲過程的實作和演化提煉(2)

測試Winform小程式,會得到成功的标志,辨別所有的斷言全部通過。

Winform開發架構之存儲過程的支援--存儲過程的實作和演化提煉(2)

本來寫到上面小節,應該就可以告一段落了,因為功能也已經完成了,而且還是支援了兩種不同的資料庫,說明我們的實作和原先的想法都是正确的。

但是,我從來不喜歡臃腫的代碼,我們留心回頭看看前面的代碼,兩種不同資料庫的實作很多是相似的,即使對于同一個資料庫(如SQLServer)的存儲過程接口實作,他們還是有很多優化的地方,代碼依舊不夠精簡和優化,本小節就是專門針對這些進行提煉和優化的。

前面的架構介紹文章,我們可以了解到,資料通路接口實作層和接口定義層一樣,都有一個基類,如基于SqlServer實作的基類為BaseDALSQL,這個基于SqlServer的資料通路基類,它也是繼承自一個超級基類(大多數的實作在這裡)AbstractBaseDAL。他們之間的繼承關系如下所示,最終我們把提煉好的内容,放到這個AbstractBaseDAL就可以了,這樣各個子類都可以進行調用,實作存儲過程的處理。

Winform開發架構之存儲過程的支援--存儲過程的實作和演化提煉(2)

對于存儲過程的實作,我們分析一下各個接口,可以看到,輸入參數是可選的,因為有些接口不需要輸出參數;輸出參數也是可選的,有些接口也不需要輸出參數,傳回的記錄類型主要有bool類型,實體類型,實體集合類型,DataTable類型這幾種,當然雖然有年齡接口的整形,但是這個是通過輸出參數來獲得的。

我們于是可以定義一個類似這樣的通用接口參數集合,用來處理需要傳回是否成功擷取帶有輸出參數的,事務對象的接口,如下所示。

它的實作基本上就是分為了幾部分,第一部分是傳入參數值(包括輸入參數、輸出參數的值),第二部是執行存儲過程,三部分是獲得輸出參數并修改值即可。

具體的實作代碼如下所示。

上面兩部分紅色哪裡,因為他們在很多其他函數裡面也通用,是以我就抽離作為一個私有函數了,就是傳入參數,和傳出結果的兩部分。

由于輸入輸出參數都是可選的,因為我們不确定它是否存在值,是以我們分别對它進行了一定的處理,具體兩個函數的代碼如下所示。

這樣我們就完成了一個普通存儲過程該接口的通用處理了,但是我們知道,還有傳回清單對象,清單集合,DataTable對象的幾種不同方式,我們也應該要對他們進行一定的封裝處理,已達到在子類能夠很好使用的目的。

下面我把整個對這幾部分封裝的代碼進行公布,它們的封裝的代碼如下所示(記得是放在超級抽象類上AbstractBaseDAL即可。

封裝好這些超級基類後,我們在資料通路層裡面,就可以很好地簡化對存儲過程的調用了,而且他們的做法都很類似,我們可以對比一下,它們調用存儲過程的實作真正簡化了很多。

例如對于SqlServer資料通路層,使用超級基類的接口,我們簡化代碼如下所示。

對于Oracle資料通路層的實作來說,它的接口實作一樣簡單,隻是參數命名有所不同而已。

以上就是我針對《Winform開發架構之存儲過程的支援--存儲過程的實作和演化提煉》這個主題進行的介紹和分析,希望對大家有所幫助,也希望結合我的架構,迅速開發各種不同的項目。

文章内容有點長,感謝您的耐心閱讀和支援。

<a href="http://www.cnblogs.com/wuhuacong/p/4130190.html">Winform開發架構之存儲過程的支援--存儲過程的實作和演化提煉(1)</a>

<a href="http://www.cnblogs.com/wuhuacong/p/4130525.html">Winform開發架構之存儲過程的支援--存儲過程的實作和演化提煉(2)</a>