ASP.NET三層架構

 本文不是從理論的角度來探討三層架構,而是用一個示例來介紹如何建設一個三層架構的項目,並說明項目中各個文件所處的層次與做用。寫本文的目的,不是爲了說明本身的這個方法有多對,別人的確定不對,而是但願給那些初學三層架構殊不知從何入手的朋友提供一點幫助。由於網上的文章,大可能是注重理論的介紹,而忽略了具體的實踐應用,或者有示例但講得不透徹。致使看了以後,理論上又學習了一遍,但仍是不知道代碼怎麼寫。因此想從這個方面入手寫一下,讓歷來沒作過三層架構的初學者也能照貓畫虎,寫出代碼來。文章表述的是筆者我的對三層架構的認識,確定有許多不足的地方,歡迎你們指正,小弟也會根據反饋來修改這篇文章。文中的代碼是僞代碼,僅用來闡明思路。數據庫

    正文:編程

    一提三層架構,你們都知道是表現層(UI),業務邏輯層(BLL)和數據訪問層(DAL),並且每層如何細分也都有不少的方法。但具體代碼怎麼寫,到底那些文件算在哪一層,倒是模模糊糊的。下面用一個簡單的例子來帶領你們實戰三層架構的項目,這個例子只有一個功能,就是用戶的簡單管理。架構

    首先創建一個空白解決方案,添加以下項目及文件ide

 

一、添加ASP.NET Web Application項目,命名爲UI,新建Web Form類型文件User.aspx(含User.aspx.cs)學習

 

二、添加ClassLibrary項目,命名爲BLL,新建Class類型文件UserBLL.csui

 

三、添加ClassLibrary項目,命名爲DAL,新建Class類型文件UserDAL.cs。添加SQLHelper引用。(這個是微軟的數據訪問類,也能夠不用,直接編寫全部的數據訪問代碼。我通常用本身寫的數據訪問類DataAccessHelper )。編碼

 

四、添加ClassLibrary項目,命名爲Model,新建Class類型文件UserModel.csorm

 

五、添加ClassLibrary項目,命名爲IDAL,新建Interface類型文件IUserDAL.cs對象

 

六、添加ClassLibrary項目,命名爲ClassFactory接口

 

相信你們已經看出來了,這個和Petshop的示例沒什麼區別,並且更簡單,由於在下也是經過Petshop學習三層架構的。但一些朋友對於這幾個項目所處的層次,以及它們之間的關係,可能比較模糊,這裏逐個說明一下:

 

一、User.aspx和User.aspx.cs

 

這兩個文件(以及文件所屬的項目,下面也是如此,再也不重複強調了)都屬於表現層部分。User.aspx比較好理解,由於它就是顯示頁面了。User.aspx.cs有些人以爲不該該算,而是要劃到業務邏輯層中去。若是不作分層的話,那麼讓User.aspx.cs來處理業務邏輯,甚至操做數據庫都沒什麼問題,可是作分層的話,這樣就不該該了。在分層結構中,User.aspx.cs僅應該處理與顯示有關的內容,其它部分都不該該涉及。

 

舉例:咱們實現用列表方式顯示用戶的功能,那麼提取信息的工做是由BLL來作的,UI(本例中是User.aspx.cs)調用BLL獲得UserInfo後,經過代碼綁定到User.aspx的數據控件上,就實現了列表的顯示。在此過程當中User.aspx.cs對UI沒有起到什麼做用,僅是用來傳遞數據,並且由於實際編碼中大部分狀況都是如此的實現,因此使有些人以爲User.aspx.cs不該該算UI,而應該併入BLL負責邏輯處理。繼續往下看,這時提出了一個新需求,要求在每一個用戶的前面加一個圖標,生動地表現出用戶的性別,並且不滿18歲的用兒童圖標表示。這個需求的實現,就輪到User.aspx.cs來作了,這種狀況下User.aspx.cs纔算有了真正的用途。

 

二、NewBLL.cs

 

添加以下方法:

 

public IList<UserInfo> GetUsers():返回全部的用戶信息列表

 

public UserInfo GetUser(int UserId):返回指定用戶的詳細信息

 

public bool AddUser(UserInfo User):新增用戶信息

 

public bool ChangeUser(UserInfo User):更新用戶信息

 

public void RemoveUser(int UserId):移除用戶信息

 

此文件就屬於業務邏輯層了,專門用來處理與業務邏輯有關的操做。可能有不少人以爲這一層惟一的用途,就是把表現層傳過來的數據轉發給數據層。這種狀況確實不少,但這隻能說明項目比較簡單,或者項目自己與業務的關係結合的不緊密(好比當前比較流行的MIS),因此形成業務層無事可作,只起到了一個轉發的做用。但這不表明業務層無關緊要,隨着項目的增大,或者業務關係比較多,業務層就會體現出它的做用來了。

 

此處最可能形成錯誤的,就是把數據操做代碼劃在了業務邏輯層,而把數據庫做爲了數據訪問層。

 

舉例:有些朋友感受BLL層意義不大,只是將DAL的數據提上來就轉發給了UI,而未做任何處理。看一下這個例子

 

BLL層

 

SelectUser(UserInfo userInfo)根據傳入的username或email獲得用戶詳細信息。

 

IsExist(UserInfo userInfo)判斷指定的username或email是否存在。

 

而後DAL也相應提供方法共BLL調用

 

SelectUser(UserInfo userInfo)

 

IsExist(UserInfo userInfo)

 

這樣BLL確實只起到了一個傳遞的做用。

 

但若是這樣作:

 

BLL.IsExist(Userinfo userinfo)

 

{

 

      UerInfo user = DAL.SelectUser(User);

 

 

return (userInfo.Id != null);

 

}

 

那麼DAL就無需實現IsExist()方法了,BLL中也就有了邏輯處理的代碼。

 

三、UserModel.cs

 

實體類,這個東西,你們可能以爲很差分層。包括我之前在內,是這樣理解的:UIßàModelßàBLLßàModelßàDAL,如此則認爲Model在各層之間起到了一個數據傳輸的橋樑做用。不過在這裏,咱們不是把事情想簡單,而是想複雜了。

 

Model是什麼?它什麼也不是!它在三層架構中是無關緊要的。它其實就是面向對象編程中最基本的東西:類。一個桌子是一個類,一條新聞也是一個類,int、string、doublie等也是類,它僅僅是一個類而已。

 

這樣,Model在三層架構中的位置,和int,string等變量的地位就同樣了,沒有其它的目的,僅用於數據的存儲而已,只不過它存儲的是複雜的數據。因此若是你的項目中對象都很是簡單,那麼不用Model而直接傳遞多個參數也能作成三層架構。

 

那爲何還要有Model呢,它的好處是什麼呢。下面是思考一個問題時想到的,插在這裏:   

 

Model在各層參數傳遞時到底能起到作大的做用?

 

在各層間傳遞參數時,能夠這樣:

 

AddUser(userId,userName,userPassword,…,)

 

也能夠這樣:

 

AddUser(userInfo)

 

這兩種方法那個好呢。一目瞭然,確定是第二種要好不少。

 

何時用普通變量類型(int,string,guid,double)在各層之間傳遞參數,什麼使用Model傳遞?下面幾個方法:

 

SelectUser(int UserId)

 

SelectUserByName(string username)

 

SelectUserByName(string username,string password)

 

SelectUserByEmail(string email)

 

SelectUserByEmail(string email,string password)

 

能夠歸納爲:

 

SelectUser(userId)

 

SelectUser(user)

 

這裏用user這個Model對象囊括了username,password,email這三個參數的四種組合模式。UserId其實也能夠合併到user中,但項目中其它BLL都實現了帶有id參數的接口,因此這裏也保留這一項。

 

傳入了userInfo,那如何處理呢,這個就須要按照前後的順序了,有具體代碼決定。

 

這裏按這個順序處理

 

首先看是否同時具備username和password,而後看是否同時具備email和password,而後看是否有username,而後看是否有email。依次處理。

 

這樣,若是之後增長一個新內容,會員卡(number),則無需更改接口,只要在DAL的代碼中增長對number的支持就行,而後前臺增長會員卡一項內容的表現與處理便可。

 

四、UserDAL.cs

 

public IList<UserInfo> SelectUsers():返回全部的用戶信息列表

 

public UserInfo SelectUser(int UserId):返回指定用戶的相信信息

 

public bool InsertUser(UserInfo User):新增用戶信息

 

public bool UpdateUser(UserInfo User):更新用戶信息

 

public void DeleteUser(int UserId):移除用戶信息

 

不少人最鬧不清的就是數據訪問層,到底那部分纔算數據訪問層呢?有些認爲數據庫就是數據訪問層,這是對定義沒有搞清楚,DAL是數據訪問層而不是數據存儲層,所以數據庫不多是這一層的。也有的把SQLHelper(或其同類做用的組件)做爲數據訪問層,它又是一個無關緊要的東西,SQLHelper的做用是減小重複性編碼,提升編碼效率,所以若是我習慣在意效率或使用一個非數據庫的數據源時,能夠丟棄SQLHelper,一個能夠隨意棄置的部分,又怎麼能成爲三層架構中的一層呢。

 

能夠這樣定義:與數據源操做有關的代碼,就應該放在數據訪問層中,屬於數據訪問層

 

五、IUserDAL

 

數據訪問層接口,這又是一個無關緊要的東西,由於Petshop中帶了它和ClassFactory類工廠,因此有些項目不論需不須要支持多數據源,都把這兩個東西作了進來,有的甚至不建ClassFactory而只建了IDAL,而後「IUserDAL iUserDal = new UserDAL();」,不知意義何在。這就徹底是畫虎不成反類犬了。

 

許多人在這裏有一個誤解,那就是覺得存在這樣的關係:BLLßàIDALßàDAL,認爲IDAL起到了BLL和DAL之間的橋樑做用,BLL是經過IDAL來調用DAL的。但實際是即便你如此編碼:「IUserDAL iUserDal = ClassFacotry.CreateUserDAL();」,那麼在執行「iUserDal.SelectUsers()」時,其實仍是執行的UserDAL實例,而不是IUserDAL實例,因此IDAL在三層中的位置是與DAL平級的關係。

 

經過上面的介紹,基本上將三層架構的層次結構說明了。其實,本人有一個判斷三層架構是否標準的方法,那就是將三層中的任意一層徹底替換,都不會對其它兩層形成影響,這樣的構造基本就符合三層標準了(雖然實現起來比較難^_^)。例如若是將項目從B/S改成C/S(或相反),那麼除了UI之外,BLL與DAL都不用改動;或者將SQLServer改成Oracle,只需替換SQLServerDAL到OracleDAL,無需其它操做等等。原本想在文中加入一些具體的代碼的,但感受不是很必要,若是你們以爲須要的話,我再補充吧。

 

總結:不要由於某個層對你來講沒用,或者實現起來特別簡單,就認爲它沒有必要,或者摒棄它,或者挪做它用。只要進行了分層,無論是幾層,每一層都要有明確的目的和功能實現,而不要被實際過程所左右,形成同一類文件位於不一樣層的狀況發生。也不要出現同一層實現了不一樣的功能的狀況發生。

相關文章
相關標籤/搜索