ASp.net 剖析三層架構
本文不是從理論的角度來探討三層架構,而是用一個示例來介紹如何建設一個三層架構的專案,並說明專案中各個檔案所處的層次與作用。寫本文的目的,不是為了說明自己的這個方法有多對,別人的肯定不對,而是希望給那些初學三層架構卻不知從何入手的朋友提供一點幫助。因為網上的文章,大多是注重理論的介紹,而忽略了具體的實踐應用,或者有示例但講得不透徹。導致看了之後,理論上又學習了一遍,但還是不知道程式碼怎麼寫。所以想從這個方面入手寫一下,讓從來沒做過三層架構的初學者也能照貓畫虎,寫出程式碼來。文章表述的是筆者個人對三層架構的認識,肯定有許多不足的地方,歡迎大家指正,小弟也會根據反饋來修改這篇文章。文中的程式碼是虛擬碼,僅用來闡明思路。
正文:
一提三層架構,大家都知道是表現層(UI),業務邏輯層(BLL)和資料訪問層(DAL),而且每層如何細分也都有很多的方法。但具體程式碼怎麼寫,到底那些檔案算在哪一層,卻是模模糊糊的。下面用一個簡單的例子來帶領大家實戰三層架構的專案,這個例子只有一個功能,就是使用者的簡單管理。
首先建立一個空白解決方案,新增如下專案及檔案
1、新增ASP.NET Web Application專案,命名為UI,新建Web Form型別檔案User.aspx(含User.aspx.cs)
2、新增ClassLibrary專案,命名為BLL,新建Class型別檔案UserBLL.cs
3、新增ClassLibrary專案,命名為DAL,新建Class型別檔案UserDAL.cs。新增SQLHelper引用。(這個是微軟的資料訪問類,也可以不用,直接編寫所有的資料訪問程式碼。我一般用自己寫的資料訪問類DataAccessHelper )。
4、新增ClassLibrary專案,命名為Model,新建Class型別檔案UserModel.cs
5、新增ClassLibrary專案,命名為IDAL,新建Interface型別檔案IUserDAL.cs
6、新增ClassLibrary專案,命名為ClassFactory
相信大家已經看出來了,這個和Petshop的示例沒什麼區別,而且更簡單,因為在下也是通過Petshop學習三層架構的。但一些朋友對於這幾個專案所處的層次,以及它們之間的關係,可能比較模糊,這裡逐個說明一下:
1、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才算有了真正的用途。
2、NewBLL.cs
新增如下方法:
public IList 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中也就有了邏輯處理的程式碼。
3、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的支援就行,然後前臺增加會員卡一項內容的表現與處理即可。
4、UserDAL.cs
public IList 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,一個可以隨意棄置的部分,又怎麼能成為三層架構中的一層呢。
可以這樣定義:與資料來源操作有關的程式碼,就應該放在資料訪問層中,屬於資料訪問層
5、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,無需其它操作等等。本來想在文中加入一些具體的程式碼的,但感覺不是很必要,如果大家覺得需要的話,我再補充吧。
正文:
一提三層架構,大家都知道是表現層(UI),業務邏輯層(BLL)和資料訪問層(DAL),而且每層如何細分也都有很多的方法。但具體程式碼怎麼寫,到底那些檔案算在哪一層,卻是模模糊糊的。下面用一個簡單的例子來帶領大家實戰三層架構的專案,這個例子只有一個功能,就是使用者的簡單管理。
首先建立一個空白解決方案,新增如下專案及檔案
1、新增ASP.NET Web Application專案,命名為UI,新建Web Form型別檔案User.aspx(含User.aspx.cs)
2、新增ClassLibrary專案,命名為BLL,新建Class型別檔案UserBLL.cs
3、新增ClassLibrary專案,命名為DAL,新建Class型別檔案UserDAL.cs。新增SQLHelper引用。(這個是微軟的資料訪問類,也可以不用,直接編寫所有的資料訪問程式碼。我一般用自己寫的資料訪問類DataAccessHelper )。
4、新增ClassLibrary專案,命名為Model,新建Class型別檔案UserModel.cs
5、新增ClassLibrary專案,命名為IDAL,新建Interface型別檔案IUserDAL.cs
6、新增ClassLibrary專案,命名為ClassFactory
相信大家已經看出來了,這個和Petshop的示例沒什麼區別,而且更簡單,因為在下也是通過Petshop學習三層架構的。但一些朋友對於這幾個專案所處的層次,以及它們之間的關係,可能比較模糊,這裡逐個說明一下:
1、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才算有了真正的用途。
2、NewBLL.cs
新增如下方法:
public IList
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中也就有了邏輯處理的程式碼。
3、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的支援就行,然後前臺增加會員卡一項內容的表現與處理即可。
4、UserDAL.cs
public IList
public UserInfo SelectUser(int UserId):返回指定使用者的相信資訊
public bool InsertUser(UserInfo User):新增使用者資訊
public bool UpdateUser(UserInfo User):更新使用者資訊
public void DeleteUser(int UserId):移除使用者資訊
很多人最鬧不清的就是資料訪問層,到底那部分才算資料訪問層呢?有些認為資料庫就是資料訪問層,這是對定義沒有搞清楚,DAL是資料訪問層而不是資料儲存層,因此資料庫不可能是這一層的。也有的把SQLHelper(或其同類作用的元件)作為資料訪問層,它又是一個可有可無的東西,SQLHelper的作用是減少重複性編碼,提高編碼效率,因此如果我習慣在乎效率或使用一個非資料庫的資料來源時,可以丟棄SQLHelper,一個可以隨意棄置的部分,又怎麼能成為三層架構中的一層呢。
可以這樣定義:與資料來源操作有關的程式碼,就應該放在資料訪問層中,屬於資料訪問層
5、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,無需其它操作等等。本來想在文中加入一些具體的程式碼的,但感覺不是很必要,如果大家覺得需要的話,我再補充吧。
總結:不要因為某個層對你來說沒用,或者實現起來特別簡單,就認為它沒有必要,或者摒棄它,或者挪作它用。只要進行了分層,不管是幾層,每一層都要有明確的目的和功能實現,而不要被實際過程所左右,造成同一類檔案位於不同層的情況發生。也不要出現同一層實現了不同的功能的情況發生。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-622488/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Asp.net 2.0三層架構的構建與理解ASP.NET架構
- asp.net標準三層架構--工廠模式ASP.NET架構模式
- 三層架構及分層架構
- 三層架構理解架構
- MVC 與三層架構MVC架構
- Java三層架構sshJava架構
- .Net三層架構 (轉)架構
- 瞭解ASP.NET底層架構ASP.NET架構
- 三層架構與養豬架構
- 【ASP.NET開發】ASP.NET(MVC)三層架構知識的學習總結ASP.NETMVC架構
- 三層架構是什麼意思 ?架構
- MVC與三層架構區別MVC架構
- 說說三層架構和MVC架構MVC
- MVC專案實踐,在三層架構下實現SportsStore,從類圖看三層架構MVC架構
- Java Web(八) MVC和三層架構JavaWebMVC架構
- 三層架構--理論與實踐架構
- DB2 pureScale的三層架構DB2架構
- Redis List 底層三種資料結構原理剖析Redis資料結構
- MVC 三層架構案例詳細講解MVC架構
- 你知道什麼是三層架構嗎?架構
- net三層架構與MVC的區別架構MVC
- 關於三層架構的一些想法架構
- EL&JSTL26_MVC&三層架構3JSMVC架構
- 基於.NET的LINQ to SQL 三層架構開發之架構建立SQL架構
- SpringBoot資料響應、分層解耦、三層架構Spring Boot解耦架構
- NAS層架構03架構
- 創新三層AI架構,打造智慧IP網路AI架構
- EdgeBoard中CNN架構的剖析CNN架構
- React Native新架構剖析React Native架構
- 大資料架構和模式(三)——理解大資料解決方案的架構層大資料架構模式
- MVC專案實踐,在三層架構下實現SportsStore-02,DbSession層、BLL層MVC架構Session
- spring框架中三層架構相關的註解Spring框架架構
- 分層架構和SOA架構
- 層次式架構案例架構
- 剖析ElasticSearch基礎分散式架構Elasticsearch分散式架構
- 雲端計算時代,資料中心架構三層到大二層的演變架構
- 關於三層架構中各層次的關係與實現模型 (轉)架構模型
- C#使用Thrift作為RPC框架入門(三)之三層架構C#RPC框架架構