版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
目錄TOC\o"1-5"\h\z實體類的設(shè)計與實現(xiàn) 2接口的設(shè)計與實現(xiàn) 13依賴注入 33數(shù)據(jù)訪問實現(xiàn)方法一:ACCESS+SQL 44?方式ー的重構(gòu) 58數(shù)據(jù)訪問實現(xiàn)方式二:SQLSERVER+存儲過程 75數(shù)據(jù)訪問的第三種實現(xiàn):基于Nbear的ORM實現(xiàn) 94業(yè)務(wù)邏輯層實現(xiàn) 107表示層實現(xiàn) 113實體類的設(shè)計與實現(xiàn)實體類是現(xiàn)實實體在計算機中的表示。它貫穿于整個架構(gòu),負(fù)擔(dān)著在各層次及模塊間傳遞數(shù)據(jù)的職責(zé)。一般來說,實體類可以分為“貧血實體類”和“充血實體類”,前者僅僅保存實體的屬性,而后者還包含ー些實體間的關(guān)系與邏輯。我們在這個Dem。中用的實體類將是“貧血實體類”。大多情況下,實體類和數(shù)據(jù)庫中的表(這里指實體表,不包括表示多對多對應(yīng)的關(guān)系表)是ーー對應(yīng)的,但這并不是ー個限制,在復(fù)雜的數(shù)據(jù)庫設(shè)計中,有可能出現(xiàn)ー個實體類對應(yīng)多個表,或者交叉對應(yīng)的情況。在本文的Demo中,實體類和表是ーー對應(yīng)的,并且實體類中的屬性和表中的字段也是對應(yīng)的。在看實體類的代碼前,先看一下系統(tǒng)的工程結(jié)構(gòu)。Solution'NGuestBook'(6projects+一メD:\VGuestBook\Yeb\(±j.切Entity1士.単Factory\±i別IBLL囹罰IDAL1£.初Utility如上圖所示,在初始階段,整個系統(tǒng)包括6個工程,它們的職責(zé)是這樣的:Web——表示層Entity——存放實體類Factory——存放和依賴注入及l(fā)oC相關(guān)的類IBLL——存放業(yè)務(wù)邏輯層接口族IDAL——存放數(shù)據(jù)訪問層接口族Utility-存放各種工具類及輔助類這只是ー個初期架構(gòu),主要是將整個系統(tǒng)搭ー個框架,在后續(xù)開發(fā)中,將會有其他工程被陸陸續(xù)續(xù)添加進(jìn)來。我們的實體類將放在Entity工程下,這里包括三個文件:Adminlnfo.cs,Messageinfo.cs,Commentlnfo.cs,分別是管理員實體類、留言實體類和評論實體類。具體代碼如下:Admininfo.cs:AdmininfousingSystem;!namespaceNGuestBook.Entity/**1111<summary>III實體類?管理員〃/</summary>[Serializable]publicclassAdmjnjnfo0]privateintid;|privatestringpassword;publicintJDget{returnthis.id;}|setイthis.id=value;}JpublijstringNameget{return;set{三value;}JpublicstringPassword]get{returnthisj)assword;)set{this.password—value;}EZEコDMessagelnfo.es:MessageinfoiusingSystem;namespaceNGuestBook.Entity/**////〈summary〉:III實體類?留言///</summary>,[SeriaHzable]publicclassMessageinfoprivateintid?|privatestringguestName;privatestringguestEmail;privatestringcontent^privateDateTimetime;privatestringreply;publicjntIDget{returnthis.id;}|set{this.id=value;}CH]publijstrinaGuestName|get{returnthis.guestName;}set{this.guestName=value;}IpublicstringGuestEmail]get{returnjthis.guestEmail^£set{this.guestEmailsvalue;}publicstringContentget{returnthis.content;}|set{this.content=value;}CH]publicDateTimeTimeget{returnthis.time;}publicstringReplyget{returnthis.reply;set{this.reply=value;}|CH]publijstringIsPassget{returnthisJsPass;}set{thjs.isPass=value;}JCommentlnfo.es:CommentinfousingSystem;namespaceNGuestBooleEntity/**////<summary>〃/實體類ー評論]//Z〈/summary〉][Serjalizable]publicclassCommentinfoprivateintid;privatestringcontent;!privatein£jnessage;publicintIDget{returnthis.id;)set{this.id=value;}JpublicstringContent(get{returnthis.content;}[set(thjs.content=value;}jget{returnthisjime;}set{this.time=value;}I nI publicint MessageI nget{returnthis.message;}set{this.message=value;}0]0大家可以看出,實體類的代碼很簡單,僅僅是負(fù)責(zé)實體的表示和數(shù)據(jù)的傳遞,不包含任何邏輯性內(nèi)容。下篇將介紹接口的設(shè)計。接口的設(shè)計與實現(xiàn)接下來,將進(jìn)行接口的設(shè)計。這里包括數(shù)據(jù)訪問層接口和業(yè)務(wù)邏輯層接口。在分層架構(gòu)中,接口扮演著非常重要的角色,它不但直接決定了各層中的各個操作類需要實現(xiàn)何種操作,而且它明確了各個層次的職責(zé)。接口也是系統(tǒng)實現(xiàn)依賴注入機制不可缺少的部分。本項目的接口設(shè)計將按如下順序進(jìn)行:.首先由前文的需求分析,列出主要的5部分。.分析各個UI需要什么業(yè)務(wù)邏輯支持,從而確定業(yè)務(wù)邏輯層接口。.分析業(yè)務(wù)邏輯層接口需要何種數(shù)據(jù)訪問操作,從而確定數(shù)據(jù)訪問層接口。另外,為保證完全的面向?qū)ο筇匦?,接口之間的數(shù)據(jù)傳遞主要靠實體類或?qū)嶓w類集合,禁止使用DataTable等對象傳遞數(shù)據(jù)。由需求分析,列出主要UI需求分析部分,請參看基于.NET平臺的分層架構(gòu)實戰(zhàn)(二)——需求分析與數(shù)據(jù)庫設(shè)計。有需求分析,可以列出系統(tǒng)中主要應(yīng)包括以下UI:UI01——主頁面,列出全部的留言及相應(yīng)評論,支持分頁顯示。留言按發(fā)表時間逆序顯示,評論緊跟在相應(yīng)留言下。管理員可以通過相應(yīng)鏈接對留言執(zhí)行通過驗證、刪除、回復(fù)以及對評論進(jìn)行刪除操作。游客可通過相應(yīng)連接進(jìn)入發(fā)表留言評論頁面。UI02——發(fā)表留言頁面,供游客發(fā)表新留言。UI03—發(fā)表評論頁面,供游客發(fā)表評論。UI04——冋復(fù)留言頁面,供管理員回復(fù)留言。UI05一管理員登錄頁面。UI06——管理員修改個人密碼的頁面。UI07——超級管理員登錄后的頁面,主要提供管理員列表??梢酝ㄟ^相應(yīng)鏈接將指定管理員刪除。UI08——添加新管理員的頁面。UI09ー操作成功完成后的跳轉(zhuǎn)提示頁面。UI10——系統(tǒng)出現(xiàn)異常時顯示友好出錯信息的頁面。由UI識別業(yè)務(wù)邏輯操作UI01:按分頁取得留言,按指定留言取得全部評論,將指定留言通過驗證,將指定留言刪除,將指定評論刪除UI02:添加新留言UI03:添加新評論UI04:回復(fù)留言UI05:管理員登錄UI06:修改管理員密碼UI07:取得全部管理員信息,刪除管理員UI08:添加新管理員經(jīng)過整理,可得以下接U操作:lAdminBLL:Add(添加管理員),Remove(刪除管理員),ChangePassword(修改管理員密碼),Login(管理員登錄),GetAII(取得全部管理員)IMessageBLL:Add(添加留言),Remove(刪除留言),Revert(回復(fù)留言),Pass(將留言通過驗證),GetByPage(按分頁取得留言)ICommentBLL:Add(添加評論),Remove(刪除評論),GetByMessage(按留言取得全部評論)這三個接口文件都放在舊LL工程下,具體代碼如下:IAdminBLL.cs:lAdminBLLusingSystem:]usingSystem.Collectjons.Generjc;usingSystem.Text]]usingNGuestBook.Entity:namespaceNGuestBook.lBLL]/**////<summary>III業(yè)務(wù)邏輯層接口?管理員III</summary>|publicinterfacelAdmjnBLL0]ド?1111<summary>|〃ノ添加管理員III<£summary>J///<paramname="admirT>新管理員實體類〈/paramp_IIIvreturns>是否成功〈/returns〉boolAdd(Adminlnfoadmin)コI**1111<summary>|〃ノjM除管理員///</summary>|///<paramname="id">欲刪除的管理員的IDv/param>;///<returns>是否成功v/returns>|boolRemove(in(id)J1**1111<summary>|〃ノ修改管理員密碼IIII</summary>|///<paramname="id">欲修改密碼的管理員的IDv/param>III<paramname="password”)新密碼v/param>///vreturns〉是否成功v/returns〉|boolChangePassword(intid,stringpassword)]I**1111〈summary〉〃/管理員登錄///</summary>|///<paramname="name"〉管理員登錄名v/param〉!!!vparamname="password”〉管理員密碼v/param〉JAdmininfoLogin(stnng^name,stringpassword);;/**1111vsummary〉j〃/取得全部管理員信,目///</summary>|III〈returns〉管理員實體類集合〈/returns,IList<Adminlnfo>GetA吼aEIMessageBLL.es:IMessageBLLibsingSystem;usingSystem.Collections.Generic;usingSystem.Text;|usingNGuestBook.Entity;namespaceNGuestBook.IBLL/**1111<summary>TiT業(yè)務(wù)邏輯層接口-留司///</summary>JpublicinterfaceIMessageBLL0]I/**III!<summary>|〃ノ添加留言I///</summary>|///<paramname="message”>新留言實體類v/param>|boolAdd(Messagelnfomessage);/**1111<summary>|//Z刪除留言III</summary>|///<paramname="id">欲刪除的留言的IDv/param>|///〈returns〉是否成功〈/returns〉boolRemoveQrHid)T]1**1111〈summary〉丨〃ノ回復(fù)留言]///〈/summary〉1///〈paramname="id”〉要回復(fù)的留言的ID〈/param〉|III<paramname="reply"〉回復(fù)信息〈/param>boolRevert(intid,stringrep卜);|ド?1111<summary>|〃ノ將留言通過驗證III</summary>|///<paramname="id">通過驗證的留言的IDv/param>IIIvreturns〉是否成功〈/returns〉boolPass(intid)コ1**1111〈summary〉丨〃ノ按分頁取得留言信息IIIIv/summary〉|///<paramname="pageSize”>每リi昆小丿し條斤L(fēng)i〈/param〉]///<paramname="pageNumber”〉當(dāng)前頁碼〈/param〉IList<Messagelnfo^GetByPage(intpageSize,intpageNumber^JロICommentBLL.esICommentBLLusingSystem;usingSystem.Collections.Generic;usingSystem.Text;usingNGuestBook.Entity;namespaceNGuestBook.lBLL/**////<summary>//Z業(yè)務(wù)邏輯層接口ー評論//Z〈/summary〉]publi^interfaceICommentBLLコI /**////<summary>|「 〃/添加評論IIIII</summary>| ///_paramname="comment,,>新評論實體類v/param> ///〈returns〉是否成功〈/returns〉boolAdd(Commen^nfocomment)jJIr*l/ll<summaryT|77T刪除評論I///〈/summary〉!///<paramname="id"〉欲刪除的評論的ID〈/param〉|boolRemove(intid);|I/**////<summary>|〃/取得指定留言的全部評論|III</summary>|///<paramname="messageld”>指定留言的IDv/param>II!〈returns〉評論實體類集合〈/returns〉IListcCommentlnfo>^GetByMessage(intmessageld)1]aD由業(yè)務(wù)邏輯確定數(shù)據(jù)訪問操作lAdminBLL需要的數(shù)據(jù)訪問操作:插入管理員,刪除管理員,更新管理員信息,按ID取得管理員信息,按登錄名與密碼取得管理員,取得全部管理員IMessageBLL需要的數(shù)據(jù)訪問操作:插入留言,刪除留言,更新留言信息,按ID取得留言信息,按分頁取得留言ICommentBLL需要的數(shù)據(jù)訪問操作:插入評論,刪除評論,按留言取得全部評論另外,添加管理員時需要驗證是否存在同名管理員,所以需要添加一個“按登錄名取得管理員”。對以上操作進(jìn)行整理,的如下接口操作:lAdminDAL:Insert,Delete,Update,GetBylD,GetByNameAndPassword,GetAIIIMessageDAL:Insert,Delete,Update,GetBylD,GetByPageICommentDAL:Insert,Delete,GetByMessage這三個接口文件放在IDAL工程下,具體代碼如下:IAdminDAL.cs:lAdminDALusingSystem;usingSystem.Collections.Generic;lusingSystem.Text;|usingNGuestBook.Entity]]namespaceNGuestBook.IDALG/**////<summary>III數(shù)據(jù)訪問層接口?管理員IIll</summary>!publicinterfaceIAdmjnDALI**////<summary>|//Z插入管理員III</summary>///<paramname="admin”>管理戻實體類v/param>]///vreturns)是否成功v/returns>|bool[nsert(Adminlnfoadmin)"/**1111<summary>|//Z刪除管理員II!〈/summary〉]///vreturns〉是否成功v/returns)boolDelete(intid)]]/**1111<summary>]///更新管理員信息///</summary>///<paramname="admirT〉管理員實體類v/param二]///〈returns〉是否成功v/returns〉boolUpdate(Admin|nfoadmin);]1**1111nummary〉]III按ID取得管理員信?///</summary>jAdmininfoGetBylD(intid)j]/**////<summary>|〃/按管理員名取得管理員信息IIII</summary>|///<paramname="name”〉管理員名v/param>///<returns>管理員實體類〈/returns)AdmininfoGetByName(stringname)jJ/**1111<summary>|〃/按用戶名及密碼取得管理員信息III</summary>|///<paramname="name”>用戶名v/param>lI〃/〈returns〉管理員實體類,不存在時返回null</returns>AdmininfoGetByNameAndPassword(stringname,stringpassword);I 1**1111<summary>|〃ノ取得全部管理員信息| ///</summary>|I ///〈returns〉管理員實體類集合〈/returns)]IListvAdminInfo"GetA”魚コ0]E 未完成 IMessageDAL.es:IMessageDAL[幽ngS^stemj]2usingSystem.Collections.Generic;3usingSystem.Text;|囪6namespaceNGuestBook.lDAL①|(zhì)8 /**////vsummary〉]8m數(shù)據(jù)訪問層接口?留言)III</summary>|publicinterfaceIMessageDAL{I** 1111<summary〉]回 〃ノ插入留言]/// </summary>| /// <paramname="message"〉留言實體類v/param〉17///<returns>是否成功v/returns〉|18 bool[nsert(Messagelnfomessage)]]回 /?二////<summaryZ]〃ノ刪除留司///</summary>|23///<paramname="id"〉欲刪除的留言的IDv/param〉JIIIvreturns〉是否成功v/returns〉boolDelete(intid);*ド.1111vsummary〉|〃ノ更新留言信息III</summary>|///<paramname="message”〉留言實體類v/param〉///<returns〉是否成功v/returns〉boolUpdate(Messagelnfomessage)イ畫/?ッ〃ノvsumrnary>\〃ノ按ID取得留言信息///</summary>|///<paramname="id”>留舌ID</param>|_ 〃/vreturns〉留言實體類〈/returns〉MessageinfoGetBylD(int id);]回■41/**////<summary〉]〃ノ按分頁取得留言信息]/// </summary〉! III<paramname="pageSize"〉每頁顯示幾條留言v/param〉III <paramname="pageNumber"〉當(dāng)前頁碼v/param〉 /〃_vreturns>留言實體類集合v/returns〉■47IList<Messagelnfo>GetByPage(intpageSize,intpageNumber);48 )畫]ICommentDAL.es:ICommentDAL1usingSystem;(2usingSystem.Collections.Generic;3usingSystem.Text;usingNGuestBook.Entity;j6namespaceNGuestBook.lDAL|8 /**////<summary>JIII數(shù)據(jù)訪問層接口ー評論IIIIv/summary>|publicinterfaceICommentDAL{13 ド?1111vsummary>|回 〃ノ插入評論I///</summary>| ///<paramname="commenビ〉評論實體類v/param>IIIvreturns>是否成功〈/returns〉bool[nsert(Commentlnfocomment);ドッ〃ノ<summary〉|〃/刪除評例踵 _///</summary〉^|///<paramname="id"〉欲刪除的評論的IDv/param〉1///vreturns〉是否成功v/returns〉|boolDelete(intjd);因27 ド”1111vsummary〉|〃ノ取得指定留言的全部評論III</summary>|///vparamjiame="messageid"〉指定留H的ID</param>|///vreturns〉評論實體類集合v/returns〉IListvCommentinfo〉GetByMessage(intmessageld);]}34)依賴注入我們設(shè)計的分層架構(gòu),層與層之間應(yīng)該是松散耦合的。因為是單向單ー調(diào)用,所以,這里的“松散耦合”實際是指上層類不能具體依賴于下層類,而應(yīng)該依賴于下層提供的一個接口。這樣,上層類不能直接實例化下層中的類,而只持有接口,至于接口所指變量最終究竟是哪ー個類,則由依賴注入機制決定。之所以這樣做,是為了實現(xiàn)層與層之間的“可替換”式設(shè)計,例如,現(xiàn)在需要換ー種方式實現(xiàn)數(shù)據(jù)訪問層,只要這個實現(xiàn)遵循了前面定義的數(shù)據(jù)訪問層接口,業(yè)務(wù)邏輯層和表示層不需要做任何改動,只需要改一下配置文件系統(tǒng)即可正常運行。另外,基于這種結(jié)構(gòu)的系統(tǒng),還可以實現(xiàn)并行開發(fā)。即不同開發(fā)人員可以專注于自己的層次,只有接口被定義好了,開發(fā)出來的東西就可以無縫連接。在J2EE平臺上,主要使用Spring框架實現(xiàn)依賴注入。這里,我們將自己做一個依賴注入容器。依賴注入的理論基礎(chǔ)是AbstractFactory設(shè)計模式,這里結(jié)合具體實例簡單介紹一下。上圖以數(shù)據(jù)訪問層為例,展示了AbstractFactory模式的應(yīng)用。如圖,現(xiàn)假設(shè)有針對Access和SQLServer兩種數(shù)據(jù)庫的數(shù)據(jù)訪問層,它們都實現(xiàn)了數(shù)據(jù)訪問層接口。每個數(shù)據(jù)訪問層有自己的工廠,所有工廠都實現(xiàn)自IDALFactory接口。而客戶類(這里就是業(yè)務(wù)邏輯層類)僅與工廠接口、數(shù)據(jù)訪問層接口耦合,而與具體類無關(guān),這樣,只要通過配置文件確定實例化哪個丄廠,就可以得到不同的數(shù)據(jù)訪問層。然而,這種設(shè)計雖然可行,但是代碼比較冗余,因為這樣需要為數(shù)據(jù)訪問層的每ー個實現(xiàn)編寫ー個エ廠,業(yè)務(wù)邏輯層也ー樣。在以前,我們亳無辦法,但是,.NET平臺引入的反射機制,給我們提供了一種解決方案。使用反射,每個層只需要ー個エ廠,然后通過從配置文件中讀出程序集的名稱,動態(tài)加載相應(yīng)類。另外,為了提高依賴注入機制的效率,這里引入緩存機制。下面來看具體實現(xiàn)。配置首先,需要在Web工程的Web.config文件的<appSeゼings>節(jié)點下添加如下兩個項:<addkey="DAL"value=""/><addkey="BLL"value=""/>這兩個配置選項分別存儲要應(yīng)用的數(shù)據(jù)訪問和也業(yè)務(wù)邏輯層的程序集名稱。value目前是空,是因為目前還沒有各個層次的具體實現(xiàn)。實現(xiàn)緩存操作輔助類為實現(xiàn)緩存操作,我們將緩存操作封裝成一個輔助類,放在Utility工程下,具體代碼如下:CacheAccess.cs:CacheAccess1usingSystem^2usingSystem.Web;busingSystem.Web.CachingjJ05namespaceNGuestBook.Utility回|7 /**////<summary>|;8 〃/輔助類,用于緩存操作:&III</summary>|10publicsealedclassCacheAccess八?〃〃〈summary〉]//Z將對象加入到緩存中/// </summary>|/// <paramname="cacheKey”>緩存鍵v/param> /// <paramname="cacheObject”>緩存對象v/param>III <paramname="dependency”〉緩存依賴項v/param>publicstaticvoidSaveToCache(stringcacheKe^objectcacheObject,CacheDependencydependency)卜9 {|20 Cachecache=HttpRuntime.Cached|21cache.Insert(cacheKey^cacheObject,dependency^22 )因24 1**1111<summary>|〃ノ從緩存屮取得對級,不存在則返回nulllIII</summary>| ///vparamname="cacheKey”〉緩存鍵v/param〉III〈returns〉獲取的緩存對象v/returns〉丨publicstaticobjectGetFromCache(string cacheKey)1Cachecache=HttpRuntime.Cache;■33returneache[eacheKeyjjJ []35 )甌!封裝依賴注入代碼因為很多依賴注入代碼非常相似,為了減少重復(fù)性代碼,我們將可復(fù)用的代碼先封裝在ー個類中。具體代碼如下(這個類放在Factory工程下):Dependencylnjector.cs:Dependencyinjector1usingSystem;2usingSystem.Configuration;3usingSystem.Reflection;4usingSystem.Web;5usingSystem.Web.Caching]]6usingNGuestBook.Utility;I08namespaceNGuestBook.Factory回/**////<summary>|〃/依賴注入提供者!〃/使用反射機制實現(xiàn)///</summary>IpublicsealedclassDependencyinjector11 {/**////vsummarはIII取得數(shù)據(jù)訪問層對象!〃/首先檢査緩存中是否存在,如果不存在,則利用反射機制返回對象20 ///<paramname="className">數(shù)據(jù)訪問類名稱v/param>]21III<returns>數(shù)據(jù)訪問層對象〈/returns〉|;22publicstaticobjectGetDALObject(stringclassName){ノヽ?〃〃vsummary>|〃ノ取得數(shù)據(jù)訪問層名稱,首先檢査緩存,不存在則到配置文件中讀取 〃/緩存依賴項為Web.Config文件];27 ///</summary>Jobject dal =CacheAccess.GetFromCacheC'DAL")7]if(dal == null)]1CacheDependencyfileDependency=newCacheDependency(HttpContext.Current.Server.MapPath(MWeb.ConfigM));dal^=ConfigurationManager.AppSettjngsf,,DALW]7|CacheAccess.SaveToCache("DAL",dal,fileDependencyJj]it i]畫36 — /**////^summary7]|37 〃/取得數(shù)據(jù)訪問層對到///</summary>]stringdalName=(string)dah]stringfullClassName= dalName+ + className;objectdalObject=CacheAccess.GetFromCache(className);if(dalObjecC==null),,3 {]CacheDependencyfileDependency=newCacheDependency(HttpContext.Current.Server.MapPathCWeb.ConfigワよdalObjectfAssem四.Load(dalName).Createlnstance(fullClassName);CacheAccess.SaveToCache(className,dalObject,fileDependency月}國returndalObject;i)叵]/?ッ〃ノ〈summary〉]〃/取得業(yè)務(wù)邏輯層對象!〃ノ首先檢查緩存中是否存在,如果不存在,則利用反射機制返冋對象/// </summary>|〃/ fparamname="className”>業(yè)務(wù)邏輯類名稱v/param二!III〈returns〉業(yè)務(wù)邏輯層對象〈/returns〉publicstatic^objectGetBLLObject(stringclassName){/**///Z〈summary〉]〃/取得業(yè)務(wù)邏輯層名稱,首先檢查緩存,不存在則到配置文件中讀取|~〃/緩存依賴項為Web.Config"文件]63 III</summary>|64 objectbll =CacheAccess.GetFromCacheC'BLL")]]65 if(bll== null)]66 (67 CacheDependencyfileDependencv=newCacheDependency(HttpContext.Current.Server.MapPath(MWeb.Config"))]]68 bll=ConfigurationManager.AppSettings["BLL"]j]69 CacheAccess.SaveToCache(2BLL\bll,fileDependency);]7Q )0〃/取得業(yè)務(wù)邏輯層對綱III</summary>|stringbllName=(string)bll;|stringfullClassName= bllName+ + className[|objectbll〇bject=CacheAccess.GetFromCache(className);|if(bllObject'==null)|(CacheDependencyfileDependencv=newCacheDependency^(HttpConte*tCurrent.Server.MapPath("Web.Configユ”bllObject=Assembly.Load(bllName).Createlnstance(fullClassName)JCacheAccess.SaveToCache(className,bllObject,fileDependency);8485return^bllObjectj!86 )87 }畫]實現(xiàn)エ丿下面使用兩個輔助類,實現(xiàn)數(shù)據(jù)訪問層エ廠和業(yè)務(wù)邏輯層エ廠。DALFactory.csDALFactory1usingSystem:fusingNGuestBook.IDALil囪4namespaceNGuestBook.Factory|6 /**////<summary>Jう〃/數(shù)據(jù)訪問層エ廠,用于獲取相應(yīng)的數(shù)據(jù)訪問層對象|BIII使用AbstractFactory設(shè)計模式+Facace設(shè)計模式+反射機制+緩存機制設(shè)計H///</summary>|publicsealedclassDALFactory11~{/?ッ〃ノ〈summary〉]〃/獲取管理員數(shù)據(jù)訪問層對到///</summary>|///<returns>管理員數(shù)據(jù)訪問層對象v/returns,publicstatic^IAdm]nDALCreateAdminDAL()” {|return(IAdminDAL)Dependency[njector.GetDALObjectf,'AdminDALj7}]]1因:21 /**1111<summaryZ]〃ノ獲取留言數(shù)據(jù)訪問層對象III </summary>|III vreturns〉留言數(shù)據(jù)訪問層對象v/returns〉publicstaticIMessageDALCreateMessageDAL(){return(IMessageDAL)DependencyInjector.GetDALObject(,'MessageDAL");任 }|0930 廣"1111vsummary>|31 〃/獲取評論數(shù)據(jù)訪問層對象貶 _III</summary〉^|33///<returns>評論數(shù)據(jù)訪問層對象v/returns〉34 public staticICommentDALCreateCommentDAL()TOC\o"1-5"\h\z§5 {]36 return(ICommentDAL)DependencyInjector1GetDALObject("CommentDAL")]]37 }138 )甌!BLLFactory.csBLLFactory1us[ngSystem;I2usingNGuestBook.lBLL;司4namespaceNGuestBooleFactory団|6 /**////<summary>|7III業(yè)務(wù)邏輯層エ廠,用,獲取相應(yīng)的業(yè)務(wù)邏輯層對象BIII使用AbstractFactory設(shè)計模式+Facace設(shè)計模式+反射機制+緩存機制設(shè)計尊///</summary>|10publicsealed^lassBLLFactory|11{I/?ソ〃/〈summary〉]〃/獲取管理員業(yè)務(wù)邏輯層對象///</summary>|ITT〈returns>管理員業(yè)務(wù)邏輯層對象〈/returns〉publicstaticlAdmjnBLLCreateAdrnjnBLLQ{return(IAdminBLL)DependencyInjector.GetBLLObject("AdminBLじ’);)回211**1111<summary>|22 〃ノ獲取留言業(yè)務(wù)邏輯層對匈23 III</summary>|24 ///vreturns〉留言業(yè)務(wù)邏輯層對象〈/returns〉因30 /**1111〈summary〉丨〃ノ獲取評論業(yè)務(wù)邏輯層對象III </summary>| /// <jetu「ns>評論業(yè)務(wù)邏輯層對象〈"e叫rns〉public staticICommentBLLCreateCommentBLL()TOC\o"1-5"\h\z(return(ICommentBLL)DependencyInjector.GetBLLObject("CommentBLL'')7l斯 }|38 )39)數(shù)據(jù)訪問實現(xiàn)方法一:ACCESS+SQL經(jīng)過上面篇文章的介紹,整個系統(tǒng)的框架算是基本搭建完了,下面,我們要具體實現(xiàn)各個層次。關(guān)于數(shù)據(jù)訪問層的實現(xiàn),我準(zhǔn)備討論三種實現(xiàn)方式,這ー篇文章討論第一種:Access+動態(tài)生成SQLo顧名思義,這種實現(xiàn)將使用Access作為后臺數(shù)據(jù)庫,而操作方式也是最基本的使用SQし命令。在具體編寫實現(xiàn)代碼之前,我們需要做ー些準(zhǔn)備工作:第一步,我們要將Access數(shù)據(jù)庫搭建完成,具體做法如下。在Web工程下新建一個文件夾,命名為AccessData,并在其中新建一個mdb文件(即Access數(shù)據(jù)庫文件),按照前面介紹過的數(shù)據(jù)庫設(shè)計構(gòu)架,將數(shù)據(jù)表及表間關(guān)系建好,這里不再贅述。第二步,我們要進(jìn)行一些配置。打開Web工程下的Web.config文件,在其中的appSettings節(jié)點下,添加如下鍵值:<addkey="AccessConnectionString"value=''Provider=Microsoft.Jet.OLEDB.4.0;DataSource={DBPath}"/>I<addkey="AccessPath"value=/AccessData/AccessDatabase.mdb"/>l第一條為Access的連接字符串,第二條為Access數(shù)據(jù)庫文件的路徑,其中“~”表示網(wǎng)站根目錄。第三步,新建一個工程。我們要新建一個工程AccessDAL,用來存放Access數(shù)據(jù)訪問層的代碼。準(zhǔn)備工作做完了,現(xiàn)在來實現(xiàn)具體的代碼。1.編寫數(shù)據(jù)訪問助手類因為很多數(shù)據(jù)訪問操作流程很相似,所以,這里將一些可復(fù)用的代碼抽取出來,編寫成助手類,以此減少代碼量,提高代碼復(fù)用性。這個助手類放在AccessDAL下,叫AccessDALHelper,主要負(fù)責(zé)Access數(shù)據(jù)庫的訪問。它包括三個方法:GetConnectionString:從配置文件中讀取配置項,組合成連接字符串。ExecuteSQLNonQuery:執(zhí)行指定SQL語句,不返回任何值,?般用于Insert,Delete,Update命令。ExecuteSQLDataReader:執(zhí)行SQL語句返回查詢結(jié)果,一般用于Select命令。具體代碼如下:AccessDALHelper.cs:AccessDALHelperusingSystem;2usingSystem.Web;3usingSystem.Web.Caching2]4usingSystem.Configuration;5usingSystem.Data;6usingSystem.Data.OleDb;7usingNGuestBook.Utility;]圓9namespaceNGuestBook.AccessDAL畫]一?〃〃〈summary〉1〃/_Access數(shù)據(jù)庫操作助手;III</summary>|publicsealedclassAccessDALHelper{/**////<summaryZ]III讀取Access數(shù)據(jù)庫的連接字符匍〃/首先從緩存里讀取,如果不存在則到配置文件中讀取,并放入緩存III</summary>| 〃/_<returns>Access數(shù)據(jù)庫的連接字符串v/return之privatestaticstringGetConnectionString(){23— if(CacheAccess.GetFromCache("AccessConnect]onString^)!=null)|
24 {25 returnCacheAccess.GetFromCache(2AccessConnectionString2).ToStrin3EstringdbPath=ConfigurationManager.AppSettingsCAccessPath;jTIstringdbAbsolutePath^HttpContexレCurrent」Server.MapPath(dbPat血stringconnectionStnng=ConfigurationManager.AppSettings[nAccessConnectionSt門ng”];]應(yīng)!CacheDependencyfileDependency=newCacheDependency(HttpContext.Current.Server.MapPath("Web.ConfigM));CacheAccess.SaveToCache("AccessCormectionString",connectionStrinqJReplace("{DBPath}",dbAbsolutePath),fileDependency)]]36 returncormectionString.Replace("£DBPath}\dbAbsolutePath);|40 ド?////〈summary〉]41 〃/執(zhí)行SQL語句并且不返回任何值[42III</summary>||44 !!!|44 !!!<paramname="parametersw>參數(shù)集合v/param>|publicstaticvoidExecuteSQLNonQueryjstringSQLCommand,OleDbParameter£]Jarametersarameters47 OleDbConnectionconnection=newOleDbConnection(GetConnectionStringi|48OleDbCommandcommand=newOleDbCommand(SQLCommand,connect!bn);I甌50for(inti=0;ivparameters.LenQth;i++)|bid52 command.Parameters.Add(parameters(i])?|反 }|回connection.Open(判command.ExecuteNonQuery();|;57connection.Close();;% }〕回60 1**1111<summary>|〃/執(zhí)行SQL語句并返回包含查詢結(jié)果的DataReader]/// </summary>|63///<paramname="SQLCommand”>所執(zhí)行的SQL命令v/param>|64 ///vparamname="parameters",參瘠集合v/param>i:65 ///<returns></returns>|66 publicstaticOleDbDataReaderExecuteSQLDataReader(stringSQLCommand,OIeDbParameter[]parameters)2 {|68 OleDbConnectionconnection=newOleDbConnection(GetConnectionStringj皿69 OleDbCommandcommand二newOleDbCommand(SQLCommand,connectbn);|瓦171 tor(inti=0;i<parameters.Length;i++)]72 {'73 command.Parameters.Add(parameters[i]);|74 }因connection.OpenQj]OleDbDataReaderdataReader=command.ExecuteReaderQj]Z/connection.Close();|四80 returndataReader;]}|運)s2.實現(xiàn)具體的數(shù)據(jù)訪問操作類因為前面已經(jīng)定義了數(shù)據(jù)訪問層接口,所以實現(xiàn)數(shù)據(jù)訪問操作類就是很機械的工作了。ド面僅以Admin的數(shù)據(jù)訪問操作類為例:AdminDAL:AdminDAL1usingSystem;2usingSystem.Collections.Generjc?]3usingSystem.Text;4usingSystem.Data;5usingSystem.Data.OleDb;[6usingNGuestBook.IDAL*]7usingNGuestBook.Entity;89namespaceNGuestBook.AccessDAL畫]11publicclassAdmjnDAL:IAdmjnDAL{13/**////<summary>]回 〃ノ插入管理員/// </summary>|III <paramname="admirT:>管理員實體類v/param>III vreturns>是否成功〈/returns〉publicboollnsert(AdmjnJnfoadrnin)]{stringSQLCommand=JJnsertinto[TAdmin]([Name]^Password])values(@name,?password)];OleDbParameter[]parameters={]newOleDbParameter(Mname",admin.Name)Jnew〇leDbParameterf2password”,admin.Password)AccessDALHelper.ExecuteSQLNonQuery(SQLCommand,parameters)J29returntrue:])/**////vsummar但〃ノ刪除管理員IIII </summary>|/// <paramname="id”>欲刪除的管理員的IDv/param>III vreturns〉崑占成功v/returns>ipublicboolDelete(intid)依 {|stringSQLCommand="deletefrom[TAdmin]where[ID]=@id^7]OleDbParameter[Xparameters={JnewOleDbParameter("id",id)包 □畫匯ス51 AccessDALHelper.ExecuteSQLNonQuery(SQLCommand, parameters)]52 returntrue;|反 }]catch]{returnfalse;///</summary>
63///<paramname="admin”>管理員實體類v/param、]64 ///vreturns〉是否成功〈/returns〉65 publicboolUpdate(Adminlnfoadmin)66 {67 stringSQLComrnand="update[TAdmin]set[Name]=@name,[Password]=?passwordwhere[ID]=@idw;|68 OleDbParameter[]parameters={,69 newOleDbParameterQid",admin.ID)]70 newOleDbParameter(Mname",admin.Name)J71 newOleDbParameterQpassword",admin.Password)ラ2 };|國74try]75 {76 AccessDALHelper.ExecuteSQLNonQuery(SQLComrnand,parameters);returntrue;returntrue;/**1111<summary^)//Z按//Z按ID取得管理員信息87///</summary>|///<paramname="id">管理員IDv/param>]///vreturns〉管理員實體類〈/returns,90 publicAdmininfoGetBylD(intid):91 192 stringSQLCommand"select*from[TAdmin]where[ID]=@id";|93OleDbParameter[]parameters={|94newOleDbParameter("id",id)99 OleDbDataReaderdataReader=AccessDALHe電er.ExecuteSQLDataReader(SQLCommand,parameters)]]100 if(dataReader.HasRows)而 {102thrownewException^;103}\104105Admininfoadmin=newAdminlnfo();106dataReader.Read();1107admin.lD=(int)dataReader["ID"]I|108admin.Name=(string)dataReader["Name"];109admin.Password=(string)dataReader["PasswordM];110111returnadmin;]也12}||113catch工14 Il叵15returnnull;117 )國119 /**////<summary>]120 〃ノ按用戶名及密碼取得管理員信息|121 III </summary>|122 III <paramname="name”>用戶名v/param>123 /// <paramname="password”〉密碼v/param>124///〈returns)管理員實體類,不存在時返回null</returns>|125publicAdminhnfoGetByNameAndPassword(stringname,stringpassword):26 (strjngSQLCommand="select*fromjTAdminJwhere[Name]=@nameand[Password]==@password"JOleDbParameterfJparameters={jJ29 new〇leDbParameter("name",name):newOleDbParameter(2password",password)J⑶―132OleDbDataReaderdataReader^AccessDALHelper.ExecuteSQLDataReader(SQLCommandparameters)JifQdataReader.HasRows)” {138 thrownewException();|139 }140141 Admininfoadmin= newAdminlnfoQ;|142 dataReader.ReadQj]
143 admin.ID=(int)dataReader["IDnj7|144 adrnin.Name^Jstring)dataReader["Name"];145 admin.Password=(string)dataReader[HPasswordM]j]146147 returnad147 returnadmin;|ロ53 }|154/**////<summary>|〃/按管理員名取得管理員信周//Z〈/summary〉] //Z〈paramname="name”>管理員名v/param>;///<returns>管理員實體類〈/returns,publicAdmin[nfoGetByName(stringname){stringSQLCommand="select*from[TAdmin]where[Name]=@name"f|OleDbParameterf]parameters={)new〇leDbParameter("name",name)J166166169169OleDbDataReaderdataReader=AccessDALHelper.ExecuteSQLDataReader(SQLCommand,_parameters);J170 ifJ^ldataReader.HasRows)Im172 throwjiewException();|17T }國175 Admininfoadmin=newAdminlnfoQ;176 dataReader.Read();177 admin.ID=Jint}dataReader["IDM];178 admin.Name^(st£[ng)dataReader["Name"];179 admin.Password=(string)dataReader「Password"];|180181returnadmin,TOC\o"1-5"\h\z182 }183catch]184 {i185 ~returnnull;|186 )18L )|188189 /**////<summaryZ]190 TiT取得全部管理員信息191 ///</summary>|192 III〈returns,管理員實體類集合〈/returns"193 public-JListvAdmininfo二GetAII()194 {195strjngSQLCommand="select*from[TAdmin]"?!196 try|198 OleDbDataReaderdataReader=AccessDALHelper.ExecuteSQLDataReader(SQLCommand,null];199i£jjdataReader.HasRows)2如 (201 thrownewExceptionQ*|2后 「203204 IList<Adminlnfo>adminCollection =newList<Adminlnfo>();|1205 inti=〇;]206 while (dataReader.Read())20r {208 Admininfoadmin=newAdminlnfoQ;|209 admimID=(int)dataReader[wID>>];|210 admin.Name=Jstring)dataReader匚Name""211 admin.Password^(string)dataReader「Password"];i212213 adminCollection.Add(admin)?|TOC\o"1-5"\h\z214 i++;|2l£ }國217 returnadmin(Dollectjon;I218 )2£9catch)2み {221 returnnull;|224 }畫可以看到,這里主要包括三種類型的操作,ー種是修改型,如Insert:ー種是返回單個實體類型,如GetBylD:還有一種是返回實體類集合型,如GetAILMessageDAL和CommentDAL的實現(xiàn)非常相似,在這里不再贅述。?方式一的重構(gòu)昨天的文章基于.NET平臺的分層架構(gòu)實戰(zhàn)(七)——數(shù)據(jù)訪問層的第一種實現(xiàn):Access+SQL發(fā)布后,很多朋友對我的程序提出了意見和建議,在這里先謝謝你們!!!尤其是金色海洋(jyk),對我的程序提出了很多建設(shè)性的意見。我大體總結(jié)了一下,昨天程序的主要缺點有:.Connection對象沒有關(guān)閉.DataReader對象沒有關(guān)閉.相似代碼太多,造成代碼冗余。其中第一點問題,目前還沒有太好的解決方案,主要是因為Connection一旦關(guān)閉,DataReader就無法讀取了。而且,Connection對象應(yīng)該會自動在適當(dāng)?shù)臅r候關(guān)閉(通過觀察臨時文件得出),并且在實際運行時并無影響(在功能上),所以這里沒有專門解決。而針對后面兩個問題,我使用了如下解決方案。對于關(guān)閉DataReader的方法,實現(xiàn)起來很簡單,在finally里將他關(guān)閉就行了。關(guān)鍵是如何去處冗余代碼。經(jīng)過我的分析,數(shù)據(jù)訪問層的操作可以分為三類:不返回數(shù)據(jù),返回單個實體類,返回實體類集合。我將這三種操作的公共部分抽出,寫成三個方法放在AccessDALHelper里,類型不同的問題使用泛型解決。這樣做有一個難題,就是不同實體在由DataReader轉(zhuǎn)化為實體類時的代碼很不一樣,無法抽出。這里,我使用了Strategy模式解決。具體做法是:首先定義ー個由DataReader轉(zhuǎn)換為實體類的策略接口,然后為不同的實體編寫不同的轉(zhuǎn)換策略,示意圖如下:可以看出,所有轉(zhuǎn)換策略都要實現(xiàn)IDataReaderToEnthyStrategy接口,并且每個策略都有一個自組合,這是以為他們都要實現(xiàn)Singはon模式。而AccessDALHelper與具體策略無關(guān),僅與接口耦合。下面來看一下具體代碼:首先是IDataReaderToEntityStrategy接口IDataReaderToEntityStrategy.cs:IDataReaderToEntityStrategy1usingSystem;2usingSystem.Collections.Generic;]3usingSystem.Text;4usingSystem.Data;5usingSystem.Data.OleDb;就^namespaceNGuestBook.AccessDAL皿[9/**///Z〈summary〉]II!由DataReader轉(zhuǎn)換成實體類的策略接川///</summary>|publicinterfaceIDataReaderToEntityStrategy<T>- {[4I**1111<summary>] //Z將DataReader轉(zhuǎn)換為實體類,采用泛空III</summary>|17//Z〈paramname="dataReader”>包含數(shù)據(jù)的DataReader對象v/param> 〃ノ〈returns〉實體類〈/returns〉TDataReaderToEntjty(OleDbDataReaderdataReader);|)甌]然后以Admin為例,看一下策略的具體實現(xiàn):AdminDataReaderToEntityStrategy.cs:AdminDataReaderToEntityStrategy1usingSystem;2usingSystem.Collections.Generic;3usingSystem.Text:4usingSystem.Data;5usingSystem.Data.OleDb;6usingNGuestBook.Entity;08namespaceNGuestBook.AccessDAL回10 /**////<summary>|11 ///DataReader到實體類的轉(zhuǎn)換策略?管理員12 〃/實現(xiàn)上使用Singleton模式,保證全局唯一實例)13III</summary>|14publicclassAdminDataReaderToEntityStrategy:IDataReaderToEntityStrategy<Adminlnfo>I15 {16privatestaticAdminDataReaderToEntityStrategysinglelnstance=null;回18 ハ?〃〃〈summary〉]19 ///私有化構(gòu)造函數(shù),保證無法外部實例化20 III</summary>|21 privateAdminDataReaderToEntitvStrategy(){}23 /?ッ〃ノ〈summary〉|24 〃ノ靜態(tài)方法,用于取得全局唯一實例]25III</summary>|26/〃vreturns>全局唯一實例v/returns〉!27publicstaticAdrninDataReaderToEntityStrategyGetlnstance()28 {29if(singleinstance==null)|TOC\o"1-5"\h\z30 (;31 singleInstance=newAdrninDataReaderToEntityStrategy();|32 }'困returnsinglelnstance;!}畫;37 /ッ〃/vsummary>|III由DataReader"轉(zhuǎn)換到管理員實體類///</summary>| /// <paramname="dataReader”>包含數(shù)據(jù)的DataReader對象v/param二41_III〈returns〉管理員實體類〈/returns〉42 publicAdmininfoDataReaderToEntity(〇leDbDataReaderdataReader),3 {|Admininfoadmin=newAdminlnfoQ;admin.ID=Xint)dataReader□D"]]]admin.Name=(string)dataReader("Name"]J]admin.Password=(stj1ng)dataReader["Password"];園49returnadmin;|50 )封}l521|可以看到,這里實現(xiàn)了一個單件模式。下ー個,是重構(gòu)后的AccessDALHelper,增加了三個方法。AccessDALHelper.cs:AccessDALHelper1usingSystem;2usingSystem.Collections.Generic?]3usingSystem.Web;4usingSystem.Web.Caching;5usingSystem.Configuration;!6usingSystem.Data;J7usingSystem.Data.OleDb;8usingNGuestBook.Utility?)日10namespaceNGuestBook.AccessDAL回/?ッ〃/<summar運〃/Access數(shù)據(jù)庫操作助手ーIII</summary>jpublicsealedclassAccessDALHelper1[17 ド.1111〈summary〉〕III讀取Access數(shù)據(jù)庫的連接字符串〃/首先從緩存里讀取,如果不存在則到配置文件中讀取,并放入緩存III</summary>|III<returns>Access數(shù)據(jù)庫的連接字符串〈/returns〉privatestaticstringGetConnectionString()|{if(CacheAccess.GetFromCache(MAccessConnectionStringw)!=null)〕21I26 returnCacheAccess
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025版土建項目施工人員勞動合同范本9篇
- 2025年倉儲果蔬存儲合同
- 2025年智能社區(qū)內(nèi)新型消費體驗商鋪租賃合同2篇
- 2025年分銷代理合作模板書
- 2025年醫(yī)療支持服務(wù)合作協(xié)議
- 2025年主題公寓租賃協(xié)議
- 2025年危險品運輸報關(guān)報檢協(xié)議
- 2025年作品使用授權(quán)合同
- 2025版外墻內(nèi)保溫系統(tǒng)施工與節(jié)能監(jiān)測合同3篇
- 2025版信用卡醫(yī)療借款服務(wù)協(xié)議3篇
- 安全常識課件
- 河北省石家莊市2023-2024學(xué)年高一上學(xué)期期末聯(lián)考化學(xué)試題(含答案)
- 小王子-英文原版
- 新版中國食物成分表
- 2024年山東省青島市中考生物試題(含答案)
- 河道綜合治理工程技術(shù)投標(biāo)文件
- 專題24 短文填空 選詞填空 2024年中考英語真題分類匯編
- 再生障礙性貧血課件
- 產(chǎn)后抑郁癥的護理查房
- 2024年江蘇護理職業(yè)學(xué)院高職單招(英語/數(shù)學(xué)/語文)筆試歷年參考題庫含答案解析
- 電能質(zhì)量與安全課件
評論
0/150
提交評論