溫皓晴 靳曉松
摘要:基于ORM思想,結(jié)合Nhibernate與NBear的優(yōu)點,提出了一種輕量級ORM數(shù)據(jù)訪問框架SqlBuilder.NET,旨在為通用數(shù)據(jù)訪問提供完整的解決方案。Sqlbuilder.NET基于C#語言編寫,主要由OracleSqlBuilder、DBOperation和SqlObjectMarker構(gòu)成。Sqlbuilder.NET具有一個事務(wù)一個日志列表、特殊字符的編解碼、查詢結(jié)果多種類型輸出和組件間的松耦合的特性,實現(xiàn)了數(shù)據(jù)新增、更新的對象化操作及對象化的復(fù)雜查詢語句生成等功能。
關(guān)鍵詞:SqlBuilder.NET;數(shù)據(jù)訪問;ORM;NHibernate;Nbear
中圖分類號:TP393文獻標志碼:A文章編號:1008-1739(2018)03-70-3
Design and Implementation of Lightweight ORM Data Access Framework SqlBuilder.NET
WEN Haoqing1, JIN Xiaosong2
(1. The No.2 High School Shijiazhuang, Shijiazhuang Hebei 050000, China; 2. The 54th Research Institute of CETC, Shijiazhuang Hebei 050081, China)
0引言
在應(yīng)用軟件項目開發(fā)中,數(shù)據(jù)訪問必不可少。為了便于系統(tǒng)的開發(fā)維護,根據(jù)“高內(nèi)聚、低耦合”的思想,通過分離數(shù)據(jù)訪問層與業(yè)務(wù)邏輯層實現(xiàn)。因此,可以設(shè)計獨立的數(shù)據(jù)訪問構(gòu)件,在不同的項目中復(fù)用。
目前比較流行的.NET數(shù)據(jù)訪問ORM框架有Nhibernate、Spring.NET及Nbear等[1-3],通過項目實踐發(fā)現(xiàn),這些框架在實現(xiàn)其高擴展性、快速開發(fā)及良好的通用性的同時,也會失去一定的靈活性和性能,顯得過于臃腫,這正是Sqlbuilder.NET產(chǎn)生的原因。
1主流數(shù)據(jù)訪問ORM框架比較
在SqlBuilder.NET設(shè)計前,先對現(xiàn)有主流.NET平臺下的ORM框架進行分析:
①Nhibernate:完整的ORM框架[4],功能強大、通用性強,而且有很多輔助工具;缺點就是配置比較多、性能低,執(zhí)行效率不理想。
②NBear:完整的ORM框架,實現(xiàn)了強類型數(shù)據(jù)庫查詢語法[5],提供代碼生成工具,性能較高;缺點是配置復(fù)雜,開發(fā)時很容易出錯,最關(guān)鍵的是框架很久未更新。
③IBatis:優(yōu)點是簡單、實用、功能完整、效率高及運行穩(wěn)定,SQL和代碼分離,提高了可維護性;缺點是配置文件多,查詢條件麻煩[6]。
2 SqlBuilder.NET的設(shè)計思想
通過經(jīng)驗總結(jié)不難發(fā)現(xiàn),數(shù)據(jù)庫的寫操作中Insert、Update和Delete一般為單表操作,讀操作Select經(jīng)常會有聯(lián)表操作,形式多樣,因此在設(shè)計框架時,寫操作可以采用對象操作的方式實現(xiàn)數(shù)據(jù)庫的操作,例如,Insert.Object(User)就可以將User對象的數(shù)據(jù)寫入到數(shù)據(jù)表中。讀操作則分為2種情況,一種是在事務(wù)操作中需要返回對象類型或?qū)ο髷?shù)組類型,便于業(yè)務(wù)邏輯編碼;另一種則只是為了將數(shù)據(jù)顯示給用戶,只需返回非對象數(shù)據(jù)類型。
因此,Sqlbuilder.NET在基于ORM思想的同時,結(jié)合了Nhibernate與NBear的優(yōu)點,既實現(xiàn)了Nhibernate類似Save(Object)插入數(shù)據(jù)的簡便操作,又實現(xiàn)了類似NBear對復(fù)雜查詢語句的對象化操作,甚至在復(fù)雜語句的支持度上比NBear還要強大。由于目前開發(fā)針對的都是Oracle數(shù)據(jù)庫,因此SQL語句對象化方面針對Oracle寫了很多函數(shù),可以使用Oracle的很多特性。
3 SqlBuilder.NET的構(gòu)成
Sqlbuilder.NET是基于C#語言編寫的輕量級對象化ORM數(shù)據(jù)訪問構(gòu)件,實現(xiàn)了類似LINQ的數(shù)據(jù)庫查詢語法,可以像使用一個.NET類的方法一樣生成SQL語句并訪問數(shù)據(jù)庫,由項目驅(qū)動開發(fā)而成,通過不斷地重構(gòu)和增加功能,目前已經(jīng)趨于穩(wěn)定。
Sqlbuilder.NET沒有XML映射文件,在性能與開發(fā)效率上做了一定的取舍,但是對性能的影響并不是很大。另外SqlBuilder.NET的設(shè)計思想避免了對象間的復(fù)雜關(guān)系,因此,Sqlbuilder.NET雖然犧牲了一定的開發(fā)效率,卻在性能上帶來了質(zhì)的飛躍。
Sqlbuilder.NET主要由以下三部分組成:
①OracleSqlbuilder:采用對象的形式生成標準SQL語句,此組件包含了Oracle數(shù)據(jù)庫的一些特性函數(shù),例如“FOR UPDATE”鎖機制;
②DBOpertion:目前實現(xiàn)了對Oracle、SqlServer、MySql和Access數(shù)據(jù)庫的增刪改查(查詢包括分頁查詢)、事務(wù)及存儲過程等操作,可以通過XML配置文件實現(xiàn)數(shù)據(jù)庫的切換,而無需更改代碼;
③SqlObjectMarker:主要是將數(shù)據(jù)庫的表生成為C#實體對象,其中表字段對應(yīng)對象的屬性,還有用于OracleSqlbuilder構(gòu)建SQL語句的特殊字段。
4 SqlBuilder.NET的特性
SqlBuilder.NET在具有部分ORM框架的特性(事務(wù)、異常)的同時,還具有以下特性:
①一個事務(wù)一個日志列表:大部分ORM框架的日志系統(tǒng)都是鏈式的,沒有分組,而SqlBuilder.NET則會一個事務(wù)對應(yīng)一個SQL列表,SQL列表中包含SQL執(zhí)行后影響的行數(shù)或者返回結(jié)果的行數(shù),提供了日志接口,可以根據(jù)系統(tǒng)需求寫入數(shù)據(jù)庫或者文件中。
②特殊字符的編解碼:SqlOracleSqlBuilder在生成SQL語句時會對數(shù)據(jù)中的特殊字符進行編碼,在DBOpertion訪問數(shù)據(jù)庫返回數(shù)據(jù)時進行解碼。不僅保證了用戶的輸入意愿,同時防止了危險字符對系統(tǒng)的威脅,還有就是該功能對于開發(fā)人員透明。
③查詢結(jié)果多種類型輸出:支持將查詢結(jié)果輸出為Datatable、Dataset及Json(String)等
④組件間的松耦合:SqlOracleBuilder與DBOpertion松耦合,2個組件可以根據(jù)項目的實際需要獨立使用,對于2個組件有關(guān)聯(lián)的地方則可以通過配置解耦。
5 SqlBuilder.NET的設(shè)計實現(xiàn)
由SqlObjectMarker連接數(shù)據(jù)庫將數(shù)據(jù)表生成特定的C#實體對象(數(shù)據(jù)表與實體對象一一對應(yīng),沒有了ORM框架對象之間的關(guān)聯(lián)),OracleSqlBuilder通過實體中的字段構(gòu)建對象化SQL,并解析成標準SQL語句,最后DBOpertion與數(shù)據(jù)庫通信通過SQL語句返回數(shù)據(jù),如圖1所示。
5.1 OracleSqlbuilder的設(shè)計實現(xiàn)
OracleSqlBuilder主要使用了泛型編程和反射機制,其過程就是將C#類型轉(zhuǎn)換成相應(yīng)SQL的特定類型,調(diào)用不同類的不同方法實現(xiàn)SQL語句的拼接,從而形成標準的SQL語句。
OracleSqlBuilder提取了數(shù)據(jù)表的通用屬性和方法,比如數(shù)據(jù)表的表名、別名及序列等,形成ModelBase類,所有的數(shù)據(jù)庫實體對象將繼承ModelBase。圖中User實體對象繼承自Modelbase,由SqlObjectMarker生成。Select、Insert、Update、Delete可以依據(jù)User表生成相應(yīng)的SQL語句,它們是由含有不同業(yè)務(wù)邏輯功能的類組成的,其類的分類主要依據(jù)SQL語句的關(guān)鍵字封裝而成,比如“Group By”及“Order By”等。
其中TableField類是OracleSqlBuilder的重要組成部分,負責字段的各種SQL函數(shù)(如SUM、Distinct和Max函數(shù))、賦值、運算以及復(fù)雜語句中子語句的生成等。
5.2 DBOpertion的設(shè)計實現(xiàn)
DBOpertion采用了設(shè)計模式中的抽象工廠模式,基于ADO.NET,同時結(jié)合反射+配置文件實現(xiàn)數(shù)據(jù)庫訪問,其中數(shù)據(jù)庫的連接字符串與數(shù)據(jù)庫類型可以在配置文件中配置,設(shè)計UML圖如圖2所示。
IDBOperation中定義了數(shù)據(jù)庫操作的通用接口,包括數(shù)據(jù)庫連接的打開關(guān)閉、SQL語句執(zhí)行、存儲過程執(zhí)行及事務(wù)處理等。OracleOperation、AccessOperation、MySqlOperation和SqlServerOperation實現(xiàn)了IDBOperation接口,DbOper則通過反射與配置文件相結(jié)合的設(shè)計思想實現(xiàn)面向IDBOperation的接口編程。
由于解除了ORM框架中對象間的復(fù)雜關(guān)系,DBOpertion可以依據(jù)業(yè)務(wù)邏輯選擇不同的返回類型,例如復(fù)雜查詢,沒有必要返回實體列表,而只需返回DataTable類型的數(shù)據(jù),減少數(shù)據(jù)到實體的轉(zhuǎn)換;在業(yè)務(wù)邏輯編寫時需要根據(jù)數(shù)據(jù)做不同的操作,那么就可以返回實體對象,整體上可以極大提高系統(tǒng)的性能。
5.3 SqlObjectMarker的設(shè)計實現(xiàn)
SqlObjectmarker實體對象生成工具采用C/S模式開發(fā),數(shù)據(jù)庫相關(guān)配置采用XML配置文件,便于一次配置和團隊開發(fā)。SqlObjectMarker可以自動獲取指定數(shù)據(jù)庫中的表及其注釋,生成的實體類會根據(jù)數(shù)據(jù)庫中的注釋加入C#注釋,便于開發(fā)時的自動提示,提高開發(fā)效率。
5.4 SqlBuilder.NET的不足
由于數(shù)據(jù)表與實體是一一對應(yīng)的關(guān)系,并且沒有XML映射文件的支持,因此在數(shù)據(jù)表發(fā)生字段變化的時候需要修改實體對象文件,造成框架的不靈活。當然框架也會存在其他的不足之處,每個框架的存在都會有它的優(yōu)勢和不足,都會在性能與功能上做一些取舍。
6結(jié)束語
SqlBuilder.NET作為一個輕量級的數(shù)據(jù)訪問框架,其設(shè)計初衷就是為了減小開發(fā)的復(fù)雜度,因此后續(xù)的應(yīng)用中,將繼續(xù)保持簡單、實用的設(shè)計理念,不會為了追求通用性而變得臃腫。希望該框架能夠在以后的應(yīng)用開發(fā)中繼續(xù)發(fā)揮作用并接受磨練,使其更加穩(wěn)定、實用。
參考文獻
[1]李斌勇,李慶.基于NHibernate的ORM映射機制研究[J].計算機技術(shù)與發(fā)展,2009,19(7):32-34.
[2]潘立武,張建平.基于NBear企業(yè)級應(yīng)用設(shè)計與開發(fā)[J].電腦編程技巧與維護,2009(13):28-33.
[3]歐勤坪,余建橋.基于SpringMVC+iBATIS框架的生物信息數(shù)據(jù)庫的設(shè)計與實現(xiàn)[J].西南大學學報(自然科學版), 2008,30(11):142-145.
[4]劉冬.NHibernate從入門到精通系列(1)[EB/OL].(2011/2/14)[2018-1-1]. http://www.cnblogs.com/GoodHelper/archive/ 2011/02/14/nhiberante_01.html.
[5] NBear Google Group.NBear常見問題集[EB/OL].(2006/12/13)[2018-1-1] https://www.cnblogs.com/fengmk2 / archive/2006/12/13/590447.html.
[6] PatrickLiu.Net環(huán)境下比較流行的ORM框架對比[EB/OL].(2016/10/25) [2018-1-1].http://www.cnblogs.com/PatrickLiu/ p/5995592.html.