剖析 .Net 下的數據訪問層技術(一)

 

l       引言

自從 .NET 真正走入開發人員那天起,“效率”兩個字就一直成爲衆多程序員津津樂道的話題。無論是從開發模式(Cross Language)、系統框架(.NET Framework),還是各種使用方便的工具(VS.NET),無一不體現出了它的勝人一籌。

同時,在另一方面,.NET 是否可以真正勝任企業級應用(Enterprise Application)開發的重任,卻依然爭論不斷,褒貶不一。

通常來說,對於一個企業級應用,需要考慮的方面很多,如安全、性能、伸縮性、易用性等。在本文中,作者更願意與大家一起探討 .NET 下數據訪問層的相關技術,這可能是在多層架構(n-Tier Architecture)誕生之日起就受到廣泛關注的敏感話題,而對於大部分開發人員來說,這也可能是項目中最讓人沮喪的部分,甚或引起爭議最多的部分。

在以下論述中,爲統一起見,作者暫時將數據訪問層簡稱爲DALData Access Layer)。

l       分析問題

簡單統計分析後,就不難發現,DAL之所以讓人畏懼,並非出於技術本身的問題,甚至恰恰相反,很多開發人員認爲這是最沒有技術含量的部分之一(就作者經歷的大小項目來看,該層所佔的開發時間一般較短,也是很多開發人員不願意承擔的“苦差”),只是架構需要或者某些思想作怪(如:爲DALDAL)才加入了這所謂的第四層(傳統三層架構並沒有提出DAL思想)。

DAL的提出,確實對傳統的架構模式提出了巨大挑戰,加入的目的肯定也是希望借其進一步提高生產效率,在這種模式下,理想情況是:大部分開發人員從此擺脫DBA之苦,甚或徹底斷絕與數據庫的直接關係,SQL之痛將離我們而去,整個OO世界從此清靜。

不過,理想歸理想,能否成爲現實則需通過項目檢驗。

 

接下來,作者試圖分析比較流行且較有代表性的幾種解決方案,看看能否從中得出一些有價值的結論,併爲我們今後在設計與實現DAL時提供一些借鑑。

 

u     ADO.NET

首先,提到.NET下的DAL,立刻映入眼簾的就是ADO.NET

沒錯,幾乎所有的DAL解決方案(請允許作者使用Solution而非

Framework)都必須從它發展而來,沒得選擇,這也是具有.NET特色的

實現方式(相比較J2EE)。

排除商業因素及CLR本身的需要,ADO.NET真正帶給我們的東西

不多,值得一提的也就DataSet(就作者經歷的項目來說,使用更多的是

DataTableDataView)。從微軟早期的內存數據庫(Memory Database

鮮有人問津到今天的DataSet大行其道,這其中的曲折實非片言隻語所

能道盡,總之,有一點可以肯定,正是有了DataSet這種選擇,.NET

DAL才能象今天這般百花齊放,大家的思路才能更趨開闊。

 

Duwamish

這方面有很多好的Sample,最經典的莫過於微軟大力推薦的企業級開發套餐:Duwamish

對於希望學習.NETDAL設計的朋友,這是一個不錯的起點,這

方面的完整剖析,大家可以參考CSDN開發高手,2003.11,本文不

再贅述。

作者自己參與的一個項目中就使用了Duwamish方案,當時限於工

期,感覺這是一個很好的參考,沒做深入分析就開始設計了。現在回想

起來,發現還是有很多不足之處。

舉個簡單的例子,Duwamish方案中並沒有考慮Cache Management

而這對於企業級應用來說,某些時候就是一個不得不考慮的問題;另一

方面,雖然Duwamish中告別了SQL語句(全部採用存儲過程實現),

但數據庫痕跡依舊十分明顯,比如:某些字段名稱的定義,關聯表名稱

的定義等等。

還有一個十分頭疼的問題是在開發過程中體現出來的。一開始,那

些比較簡單的數據表還比較容易實現,到了一些包含相互關係的數據表

時,我們的DAL工程師就感到了壓力,到後來,幾乎又做了一遍DBA

在數據庫建模時早已做過的工作,只不過,這次將數據庫腳本換作了

C# 實現(或者說:將數據庫結構換成了表面上具有OO特色DataSet

而已。

可能,Duwamish的實現比較經典,但在實際應用中,有時並不意

味着Best Practice。就拿我們的項目來說,雖然成功交付,但無論從模

型複用角度,還是開發效率來說,都不能算很成功。套用一句流行語:

其實我們可以做得更好!

 

PetShop

ADO.NET上另一個值得參考的DAL實現就是鼎鼎大名的PetShop

當然了,與Duwamish相似,名氣大未必真的實用。PetShop雖然

彌補了Duwamish在某些方面的不足,例如:通過Factory支持多種數

據庫存儲,引入了Cache機制,提供了更爲便利的SQL Helper,但也同

時帶來了另一些問題。其中,最麻煩的就是SQL語句的引入,而且還

是針對不同數據庫存儲的不同SQL語句(主要是SQL ServerOracle

的參數表示方式不同)。

另一方面,PetShop雖然沒有使用DataSet而代之以更爲簡潔的普通

實體對象(Model),但它還是將DataReader的結果轉換到了包含實體對

象的列表集合中供離線使用,從這個意義上說,可謂換湯不換藥。甚至,

在某些場合,例如:需要進行數據過濾,或者在主從數據間導航,反而

更爲不便(此時,簡單的Collection或者List是無法滿足需求的,DBA

DAL開發人員只能再提供其它的方法來達到目的)。

 

從上述兩個例子中,我們可以看出,即使在微軟的開發團隊中,也

沒有能夠在DAL這個問題上達成一致。這方面的更詳細信息,有興趣

的朋友可以參考如下文章:

http://www.microsoft.com/china/community/Column/67.mspx

 

實戰

上面剖析的兩個解決方案,讓我們看到了它們各自的優勢與不足,而企業級應用的複雜環境也不太可能要求一個放之四海而皆準的框架就能解決所有難題,因此,只能根據具體情況具體分析。

作者曾經參與一個(.NET)大型外包項目的開發工作,有幸一睹其DAL的設計思想,深感震撼,在此與各位朋友一起共同探討。

SQL Server所帶Northwind數據庫爲例,如下就是一段基於該DAL的調用代碼(作者做了一些名稱上的調整):

 

// 根據EmployeeID返回其Title

boEmp = new EmployeeDAL();

boEmp.Keys[“Emp_ID”] = 1; // 注意:實際字段名爲:EmployeeID

boEmp.Select();

string strTitle = boEmp[“Emp_Title”]; // 注意:實際字段名爲:Title

……

// 根據 City 返回所有符合條件的 Employee

boEmp = new EmployeeDAL();

boEmp.Keys[“Emp_City”] = “Seattle”;

boEmp.Select(); // 注意:該方法與上面的調用完全相同

DataTable dtEmp = boEmp.Table;

 

如果不考慮對象創建(可以採用Object Pooling或者Cached Object)以及調用後的處理,實際的代碼只有兩行!

更讓人吃驚的是,上述EmployeeDAL類沒有任何真正意義上的實現代碼,僅僅是聲明瞭類名,然後從一個通用基類繼承而已!!

最優雅的地方還不在於此,實際上,就算在那個基類中,也根本看不到SqlConnection或者OracleAdapter之類的幫派之爭。

相信大家也猜出來了,沒錯,它是借鑑了PetShop的實現,採用了Factory模式來保證DAL可以適用於不同的數據庫存儲。不過,這種實現與PetShop還是有很大的區別:至少,它沒有產生不同的SQL語句,更沒有出現不同的參數調用方式(SQL Server中一般使用“@”符號,Oracle中一般使用“:”符號),所有幫派一視同仁!

這其中,當然得益於Factory的實現技巧,但更重要的因素還在於設計方式的精妙。其實,在.NET Framework中,已經提供了這種設計方式的基石,說白了,就是System.Data中的那些Interface(如:IDBConnectionIdataAdapter等)。

在這樣的設計基礎上,我們針對每一個DAL類,就不再需要爲不同的數據庫存儲提供不同的數據存取實現了。例如:在PetShop中,針對訂單數據需要實現Order類,很自然的,系統爲SQL ServerOracle分別實現了Order類並使用不同ProviderSqlClientOracleClient)提供的方法進行操作。而在實際調用時,PetShop通過Factory模式動態創建真正的Order類並激活相應的方法,一個面向不同數據庫存儲的方案就躍然紙上。

其實,PetShop這種方案已經比較靈活了,如果更能省去“撰寫不同Order類”之苦,那就真的送佛送到天了J。而所有這些功能,在作者所參與的這個項目中,已經完全搞定了!

至於上面的“EmployeeDAL(當然,包括其它所有DAL類)沒有任何真正實現代碼”,只不過玩了一個小小的配置技巧而已:將不同的DAL類與相關的Stored Procedure(請注意:不是TableView)按照Namespace分別存儲到XML文件中。

可能大家已經看出來了,理論上,甚至只需要一個DAL類就可以完成上述所有的工作!但在實際操作中,不同的DAL類可能還是有一些數據處理上的細微差別(比如:數據校驗,格式轉換等)。

總的來說,在這樣一個大項目中,不可能要求所有開發人員(除了DBADAL Framework Developer)都去了解ADO.NET的方方面面,雖然作者對此頗有研究,但在這個項目中,卻從頭至尾只用到了兩個類DataTableDataView(甚至連Transaction都無需瞭解)!

 

 

作者簡介:

本文作者張雪峯  微軟(中國)有限公司 的諮詢顧問。他目前在中國上海 微軟顧問諮詢部門工作,從事 .NET 技術的研究以及相關項目的開發。可以通過 [email protected] 與他聯繫。

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章