NET 分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之三 數(shù)據(jù)訪問深入一點(diǎn)的思考_第1頁
NET 分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之三 數(shù)據(jù)訪問深入一點(diǎn)的思考_第2頁
NET 分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之三 數(shù)據(jù)訪問深入一點(diǎn)的思考_第3頁
NET 分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之三 數(shù)據(jù)訪問深入一點(diǎn)的思考_第4頁
NET 分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之三 數(shù)據(jù)訪問深入一點(diǎn)的思考_第5頁
已閱讀5頁,還剩4頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

[原創(chuàng)].NET分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之三數(shù)據(jù)訪問深入一點(diǎn)的思考.NET分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之三數(shù)據(jù)訪問深入一點(diǎn)的思考前言:首先,感謝園子里的朋友對文章的支持,感謝大家,希望本系列的文章能夠真正的對大家起到一點(diǎn)幫助的作用。再次感謝大家。大家也許想問,什么時候出代碼,代碼一定會出的,我不想一上來就開始拋出一大堆的代碼,然后講解,架構(gòu)的設(shè)計在思考的過程,思考到了,代碼也就水到渠成了。上篇文章講述在設(shè)計之初,Richard所畫出的一些草圖,本篇對之前的草圖做了進(jìn)一步的思考。本篇的議題如下:.草圖的一些問題在哪里重審之前項目中數(shù)據(jù)層的問題思維的一點(diǎn)突破回首再看數(shù)據(jù)訪問層1.草圖的一些問題在哪里當(dāng)Richard把草圖畫出來了之后,想到了另外的一個問題:在DAL數(shù)據(jù)層之間提供的那個接口層到底應(yīng)不應(yīng)該是ServicesInterface。其實(shí)這個接口層是普通的Interface層還是ServicesInterface,Richard也拿不定主意的,因為當(dāng)初之所以要把這個接口層改為ServicesInterface,是因為在數(shù)據(jù)源提供者(ServiceAgent)那塊給了他“靈感”——數(shù)據(jù)源可以使用遠(yuǎn)程的Services?;谶@個思想,所以Richard也考慮到了:也許,現(xiàn)在設(shè)計的這個DAL,哪一天會作為服務(wù)給其他的程序提供數(shù)據(jù)也不說定。雖然,這個問題對現(xiàn)在來說不是那么的重要,但是在Richard的心里,無法說服自己到底使用哪一種接口層(也許是Richard這個人的性格有關(guān)吧,一定要給個理由說服自己,但是這個理由又不能隨隨便便的糊弄自己)。Richard想到了之前在開發(fā)項目的時候,也確實(shí)曾經(jīng)把其他公司提供的服務(wù)作為數(shù)據(jù)源的情況。當(dāng)時的調(diào)用雖然只是進(jìn)行查詢,增加,刪除,修改的簡單操作,但是很多的流程已經(jīng)在服務(wù)提供者那邊定義好了,例如在發(fā)送一批貨物的時候,Richard只是調(diào)用了服務(wù)接口的一個CreateProduct(Productproduct)方法,但是在服務(wù)器那端卻做了很多的事情:計算庫存,生成訂單,選擇貨物供應(yīng)商等等。這樣說來,如果現(xiàn)在Richard把DAL上面加上一個ServicesInterface層,那么DAL或者其他的層就必須提供很多的邏輯操作,或者不一定是邏輯操作,還可以是數(shù)據(jù)格式驗證、身份驗證。如果真的這樣設(shè)計,那么數(shù)據(jù)層的做的事情就很多了,要很多的邏輯。而這些邏輯在BLL中進(jìn)行才是比較好的選擇,想到這里,Richard似乎開始明白:把ServicesInterface層放在BLL層之上。這樣就可以充分的利用BLL的邏輯驗證功能。所以DAL之上的接口層,還是決定采用普通的接口。2.重審之前項目中數(shù)據(jù)層的問題Richard在數(shù)據(jù)層DAL這塊花了大量時間來思考,其實(shí)是有原因的。在之前的項目中,數(shù)據(jù)層的設(shè)計顯得很臃腫,而且在Richard看來,這些代碼已經(jīng)可以用一種比較通用的方式來寫,沒有必要寫那么復(fù)雜的代碼。例如,在EmployeeDAL中有以下的方法:代碼publicEmployeeGetEmployeeById(stringemployeeId);publicEmplpyeeGetEmployeeByName(stringemployeName);publicstringGetEmployeePositionById(stringemployeeId);publicintGetEmployeeCount();這樣寫,沒有錯。但是有一點(diǎn)引起了Richard的思考:DAL類中,很多的方法基本上都是查詢的方法,而Add,Update,Delete在很多的DAL類中形式都比較的統(tǒng)一,特別是在使用了Linq,EntityFramework之后,所有的數(shù)據(jù)實(shí)體類Add,Update,Delete方法幾乎是一樣的,如在Linq中可以使用DataContext.GetTable<T>().InsertOnSubmit(entity)方法來插入任何的數(shù)據(jù)實(shí)體類。但是就只有這些不同條件的查詢方法很難統(tǒng)一,幾乎是每個不同的DAL都要去實(shí)現(xiàn)自己的一些特有的查詢方法。但是Richard認(rèn)為把這些方法統(tǒng)一是有可能的,甚至是達(dá)到那種“以不變應(yīng)萬變的”效果才好,帶著這個想法Richard開始進(jìn)行很多的嘗試。3.思維的一點(diǎn)突破Richard極力的在自己的腦海搜尋解決的方案,也翻閱自己之前下載和買過的書籍,看看那些是否與查詢數(shù)據(jù)有關(guān),只要看到有“查詢”兩個字的章節(jié),Richard就不會放過。也參看了.NET的一個知名開源Framework的設(shè)計思想。給了他提示的就是Fowler<<企業(yè)應(yīng)用架構(gòu)模式>>一書,書中提到的查詢對象(QueryObject),Richard參看了之后第一反應(yīng)就是:確實(shí)不錯,但是太抽象了,沒有給出一些示例。其實(shí)之前Richard在看這本書的時候,認(rèn)為書的高度太高了,Richard幾次攻讀,都是深受打擊。所以,結(jié)果是Richard很敬畏這本書,但是還是想有朝一日能夠拿下它?,F(xiàn)在書中就有了查詢對象的一些解決方案和實(shí)現(xiàn),Richard硬著上了。Richard認(rèn)為:很多的事情不是等你的所有條件都具備才去做的,事情往往是在你還沒有準(zhǔn)備好的情況下就已經(jīng)發(fā)生了,凡事都有一個開頭,做架構(gòu)也是這樣的,開始設(shè)計一個架構(gòu)的時候,并且不是說明你已經(jīng)完全的把所有技術(shù)都掌握了,完美了,肯定是有一個開始嘗試的過程。可能在開始設(shè)計的時候,漏洞百出,但是思維的周密性也是這樣慢慢的鍛煉出來的。平時在思考的時候,自己站在一個高一點(diǎn)的角度看問題(現(xiàn)在是開發(fā)人員,但是開發(fā)人員在設(shè)計和開發(fā)的時候可以這樣想:如果我是架構(gòu)的設(shè)計者,我會怎么做?),思維的高度上去了,機(jī)會到來的時候也就從容了。Richard開始重新理解查詢對象。其實(shí)查詢對象就是在一定程度上隱藏了SQL語句,查詢對象是解釋器模式的一種應(yīng)用,實(shí)際上查詢對象最后還是要解釋為SQL語句到數(shù)據(jù)庫中去執(zhí)行的(不管在中間過程是如何一步步的操作這個查詢對象,因為數(shù)據(jù)庫現(xiàn)在只是認(rèn)識SQL,所以查詢對象最終還是要生成SQL語句)。查詢對象主要用途就是使得客戶程序可以構(gòu)造各種的查詢,而且查詢中使用的都是與業(yè)務(wù)類有關(guān)的屬性,這就意味著,客戶程序不用了解數(shù)據(jù)庫的表名和列名。這種做法最直接的好處就是業(yè)務(wù)開發(fā)的人員不用知道數(shù)據(jù)庫的構(gòu)造。而且如果查詢對象的設(shè)計是以接口的形式出現(xiàn),那么靈活性就更加的大。例如,設(shè)計一個IQuery的查詢對象接口,然后,在架構(gòu)中有兩個實(shí)現(xiàn)了IQuery接口的查詢對象,如LinqQuery,EFQuery,這兩個具體的查詢對象最終會被分別解釋為Linq和EntityFramework可以識別的語句,再通過Linq和EntityFramework去執(zhí)行數(shù)據(jù)操作。在程序中就可以通過配置來決定使用哪種查詢對象和使用哪種數(shù)據(jù)訪問技術(shù)。越來越多的想法在Richard的腦海中出現(xiàn),而隨之帶來的問題也開始堆積?;镜乃枷胧怯辛?,但是實(shí)現(xiàn)起來那就得是另外的一回事了。怎么把這些思緒理清,怎么把這些理清的思緒變?yōu)榇a的實(shí)現(xiàn),這個成為了擺在Richard面前最現(xiàn)實(shí)的難題。但是不管怎樣,已經(jīng)有了一點(diǎn)點(diǎn)的進(jìn)展,記得當(dāng)初考慮的時候還是頭腦一片空白,現(xiàn)在的想法一個接著一個,在思維上進(jìn)步了。Richard覺得有點(diǎn)欣慰。4.回首再看數(shù)據(jù)訪問層有了上面的思考,Richard再次審視了DAL,開始發(fā)覺:DAL其實(shí)就只是一個存取數(shù)據(jù)和操作數(shù)據(jù)的地方,這就是DAL的主要功能。現(xiàn)在數(shù)據(jù)層的設(shè)計基本上已經(jīng)可以實(shí)現(xiàn)了,而且可以做到“以不變應(yīng)萬變”,不管BLL中對數(shù)據(jù)進(jìn)行什么樣的操作,在DAL層都可以用那個四種增,刪,查,改的方法搞定。本篇就到這里,謝謝各位!下篇講述:.NET分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之四構(gòu)建從理想和實(shí)現(xiàn)之間的橋梁[原創(chuàng)].NET分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之四構(gòu)建從理想和實(shí)現(xiàn)之間的橋梁(前篇).NET分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之四構(gòu)建從理想和實(shí)現(xiàn)之間的橋梁(前篇)前言:上一篇文章講述了一些實(shí)現(xiàn)DAL的理論,本篇主要是DAL實(shí)現(xiàn)的的初步的嘗試。本篇的主要議題如下:1.設(shè)計DAL的基本操作2.對基本的操作的進(jìn)一步的思考3.查詢對象的一些思考1.設(shè)計DAL的基本操作Richard認(rèn)為:在設(shè)計一個架構(gòu)或者Framework的時候,有幾點(diǎn)很重要:a.總體把握的能力。b.抽象的能力。c.分析的能力首先,從總體上來看,Richard認(rèn)為DAL中最基本,而且最容易想到的方法就是CRUD(Create,Read,Update,Delete)四個操作。于是Richard在草紙寫出了基本操作的名稱:AddSingleDataEntity;AddDataEntityList;UpdateSingleDataEntity;UpdateDataEntityList;DeleteSingleDataEntity;DeleteDataEntityList;GetSingleDataEntiry;GetDataEntityList;上面列出的方法名字很長,其實(shí)Richard在思考這些方法的名稱的時候也參考了.NET設(shè)計規(guī)范中的一些建議:方法名稱要具有“自解釋性”,因為架構(gòu)的設(shè)計最后還是給開發(fā)人員用的,所以方法的定義要一眼就看出它是干什么的,而且規(guī)范的命名也可以大大的減少維護(hù)的成本。(可能這些名字的命名有點(diǎn)對規(guī)范的“生搬硬套”,但是之后會慢慢的重構(gòu)的)從總體出發(fā),已經(jīng)定義出了基本的操作,那么現(xiàn)在就開始一步步的分析,如何實(shí)現(xiàn)這些方法。Richard開始思考第一個方法的實(shí)現(xiàn),其實(shí)Richard心里也清楚:其實(shí)到底哪個方法作為第一個來考慮也許很重要,但是在一切都不清楚之前起碼要拿一個來入手,而且隨著思考的深入,很多的問題都會慢慢的浮現(xiàn),到時候一切就會明晰起來。對于AddSingleDataEntity這個方法,首先就要考慮這個方法到底要把什么添加到數(shù)據(jù)庫中,也就是說要考慮這個方法的參數(shù),而且這個參數(shù)要足夠的“兼容”,因為之前Richard就是想設(shè)計出一個“以不變應(yīng)萬變”的DAL。在考慮這個參數(shù)問題之前,首先Richard很清楚:在.NET數(shù)據(jù)訪問技術(shù)中,Linq,EntityFramework等ORM技術(shù)已經(jīng)廣泛的應(yīng)用,所以在設(shè)計DAL的時候要充分的考慮到現(xiàn)有的一些技術(shù)(盡量避免重新造輪子)。而且在數(shù)據(jù)是如何被存入到數(shù)據(jù)庫中的以及數(shù)據(jù)是如何從數(shù)據(jù)庫中取出的,這個工作是完全可以交給這些ORM的,最后的結(jié)果就是:在DAL中只是操作這些ORM的那些映射實(shí)體?;谶@個想法,Richard就確定了:AddSingleDataEntity參數(shù)是一個數(shù)據(jù)實(shí)體。(本系列文章約定:數(shù)據(jù)實(shí)體,即DataEntity,就是ORM對一個數(shù)據(jù)庫表進(jìn)行映射后產(chǎn)生的實(shí)體和數(shù)據(jù)庫中的表一一對應(yīng),如在數(shù)據(jù)庫中有一張Employee表,LinqtoSql將會把它映射成為Employee的一個類,這個類就稱為數(shù)據(jù)實(shí)體)。因為這些方法最終是操作數(shù)據(jù)實(shí)體的,所以包含這些方法的接口名字就定義為IDataContext。因為不同的表產(chǎn)生不同的數(shù)據(jù)實(shí)體,但是Richard還想使得AddSingleDataEntity這個方法可以接受任何的數(shù)據(jù)實(shí)體,所以此時很有必要對數(shù)據(jù)實(shí)體進(jìn)行抽象。所以Richard想到了定義一個接口:IDataEntity,打算讓所有通過ORM生成的數(shù)據(jù)實(shí)體都繼承這個接口。而且Richard還想到:1.如果BLL直接引用DAL使用的,那么IDataEntity可能會在BLL中出現(xiàn)的。2.如果BLL通過repository去DAL中獲取數(shù)據(jù),那么到時候BLL可能都不會直接引用DAL,但是BLL最終還是得使用數(shù)據(jù)做事情,所以IDataEntity還是會在BLL中出現(xiàn),所以,IDataEntity接口最好定義在一個公共的地方。Richard決定新建一個Common的類庫,加入IDataEntity接口的定義,現(xiàn)在這個接口里面什么都沒有,只是一個標(biāo)記而已,表明繼承這個接口的類就是數(shù)據(jù)實(shí)體類。AddSingleDataEntity(IDataEntitydataEntity);還有一點(diǎn)就是盡量的使用類型安全的方法,于是Richard把方法改成了范型方法:AddSingleDataEntity<T>(TdataEntity)whereT:IDataEntity,class,new();至于T的那些約束:T:IDataEntity,class,new(),是考慮到了Linq和EF中對數(shù)據(jù)實(shí)體的一些要求。一般的Add方法都是返回添加是否成功,true或者false,方法再次改造:boolAddSingleDataEntity<T>(TdataEntity)whereT:IDataEntity,class,new();然后Richard就寫出了上面列出的一些方法的定義:boolAddSingleDataEntity<T>(TdataEntity)whereT:class,IDataEntity,new();boolAddDataEntityList<T>(List<T>dataEntityList)whereT:class,IDataEntity,new();boolDeleteDataEntityList<T>(List<T>dataEntityList)whereT:class,IDataEntity,new();boolDeleteSingleDataEntity<T>(TdataEntity)whereT:class,IDataEntity,new();boolUpdateSingleDataEntity<T>(TdataEntity)whereT:class,IDataEntity,new();boolUpdateDataEntityList<T>(List<T>dataEntityList)whereT:class,IDataEntity,new();至于GetDataEntityList,按照之前的查詢對象的想法,傳入一個IQuery的接口:List<T>GetDataEntityList<T>(IQueryquery)whereT:class,IDataEntity,new();2.對基本的操作的進(jìn)一步的思考確實(shí),上面那些基本操作是沒有什么問題的,現(xiàn)在Richard又考慮到了另外的一些問題,還是以AddSingleDataEntity方法為例:a.有些時候,不僅僅要知道插入數(shù)據(jù)是否成功,而且還想返回新加入數(shù)據(jù)在數(shù)據(jù)庫中的主鍵信息來做其他的用途。怎么辦?再來查詢一次?b.如果插入失敗了,僅僅只是返回一個false嗎?可能其他的調(diào)用模塊想知道到底是發(fā)生了什么異常而導(dǎo)致的插入失敗,而且其他的模塊對于發(fā)生的異常有自己的處理方法,所以AddSingleDataEntity要提供足夠的信息?;谏厦娴乃伎迹赃@個基本的操作方法不能只是簡單的返回一些簡單的值就完了。也就是說,這些方法要返回一個數(shù)據(jù)包:里面包含很多信息,以便其他的調(diào)用模塊來使用這些信息,感覺有點(diǎn)像是C#事件中的eventArgs.所以Richard在Common的那個類庫中加入一個對象,定義如下:代碼publicclassDataResult<T>whereT:IDataEntity{publicList<T>EntityList{get;set;}publicboolIsSuccess{get;set;}publicExceptionException{get;set;}publicobjectCustomData{get;set;}}這個類最后將會作為方法的返回結(jié)果。Richard發(fā)覺,上面的方法確實(shí)是很有”自解釋性”,但是很多的開發(fā)人員對這些CRUD操作的名字都很熟悉了,而且最后開發(fā)的出來的架構(gòu)的使用者還是開發(fā)人員,應(yīng)該符合他們的習(xí)慣,所以Richard改變了方法的名字,改變后的版本如下:代碼publicinterfaceIDataContext{IList<T>Query<T>(IQueryqueryCondition)whereT:class,IDataEntity,new();IList<T>Que

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論