【ASP.NET開發】.NET三層架構簡單解析

這篇文章原本應該很早就寫出來的,可是一直苦於本身的精神能力有限,並且已經到了咱們學校的考試周,因此時間上仍是有點緊迫。關鍵的一點就是,找不到合理的思路來寫,思路沒有的話,就算是再好的素材,也寫不來你們喜歡的文章。程序員

以前已經寫過關於.NET三層架的兩篇文章了,一篇是《【ASP.NET開發】ASP.NET(MVC)三層架構知識的學習總結》《【ASP.NET開發】ASP.NET對SQLServer的通用數據庫訪問類》。若是你們有興趣的話,能夠去讀一讀。固然了,這兩篇文章的內容,大部分都不是本身的,本身也是看了別人的博文,而後本身總結一下,拿過來本身用罷了。此次的文章主要是本身親自使用這些知識作了一個項目(咱們學校資環學院的院網站),而後拿出來跟你們分享一下。也不要指望博主可以寫出多麼有水平的文章,我仍是學生(大三),我也是在學習的過程當中,寫博客之不過是想記錄本身學習過程當中的點滴和記錄本身的進步,若是可以順便的幫助別人學習就更好了。同時也但願你們可以多給我提意見。web

很是感謝博客園博友 @ 守護晴天,@Adming,@ Qlin等博友給我提出的寶貴的修改意見。也但願你們在閱讀本博文的時候,若是有什麼問題,或者疑問及時的給我留言溝通,你們一塊兒探討。sql

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------數據庫

對於三層架構來講,主要是使用設計模式的思想,對於項目的各個模塊實現"高內聚,低耦合"的思想。這裏就不作詳細的介紹了,若是你們有興趣,能夠閱讀軟件工程和設計模式相關文章。設計模式

咱們能夠先來看一個圖,來大概的瞭解一下,三層架構所要表達的思想。數組

我之前本身作的圖,被你們指出了不少的錯誤。因此,我就引用了網絡上的一個圖片來解釋(若是侵害了您的版權,請您聯繫我網絡


對於三層架構來講,就是使用類,把咱們在作項目的過程當中,可能須要反覆操做數據庫,反覆的使用某個方法等等,可能就是操做的參數不一樣。若是咱們若是在每次使用的時候,都去編寫相應的代碼,無疑會增長程序員的負擔。因此,爲了增長方法的重用,就把這些可以重用的方法抽象成類,以供程序員在其它地方能夠調用。架構

固然了,這也是面向對象的一部分。其中的三層所指的就是:①視圖層(UI)②數據庫訪問層(DAL)③業務邏輯層(BLL)。固然了,還有所謂的第四層-實體層(model),這一層主要是在這三個層之間進行流動傳遞。可是爲何不叫四層架構。。。緣由我也不知道,多是由於實體層是外在的能夠根據須要會隨時變化的(如:項目後續模塊的添加等)。而其它三個層,若是搭建完後,能夠做爲框架來使用的。。。框架

1)首先仍是先來介紹一下實體層吧,就是咱們一般所說的modelide

實體就是咱們在開發項目過程當中所要涉及的一些對象。把這些所要涉及的對象(如:新聞名稱,新聞上傳時間,供稿人,上傳文件的名稱等),都抽象成一個類。使用封裝字段方法,咱們能夠在視圖層通(主要是視圖層)過實例化對象的方法,來給咱們的對象的屬性賦值。

簡單的看一段代碼吧,可能會可以更加的清楚,明白


  
  
  
  
  1. publicclass NewsModel

  2. {

  3. //新聞編號

  4. privateint nNewsId;

  5. publicint NNewsId

  6.    {

  7. get { return nNewsId; }

  8. set { nNewsId = value; }

  9.    }

  10. //新聞名稱

  11. privatestring strNewsName;

  12. publicstring StrNewsName

  13.    {

  14. get { return strNewsName; }

  15. set { strNewsName = value; }

  16.    }

  17. }

這裏的NewsModel就是一個關於新聞的實體類,其中聲明瞭兩個private的屬性字段(必定要是private,防止非法賦值),使用public的構造函數,能夠在外部給字段賦值。


下面的就是在視圖層來實例化對象,根據須要來給字段賦值,看下面的一段代碼:


  
  
  
  
  1. NewsModel newModel = new NewsModel();

  2.       newModel.StrNewsName = this.TextBox1.Text;

固然了,這僅僅是一段代碼,其中並無給字段nNewsId賦值,由於我把它做爲數據庫的id地段,已經設置成自動增加。這樣,就完成了視圖層對實體層的調用。


2)數據庫訪問層

數據庫庫訪問層,顧名思義,就是主要來完成對數據庫的訪問,等一系類的對數據庫操做的類。爲何要單獨的把對數據庫的操做抽象成一個單獨的類,我我的理解是由於在整個項目的開發過程當中,不只僅須要一次訪問數據庫,而是須要屢次,若是每次都編寫數據庫訪問代碼的話,會增長程序員的我的工做量,並且對於代碼的易用性和簡潔性來講確定是很是糟糕的。固然來可能還有其它的一些優勢,我暫時尚未發現。

既然是對數據庫的操做類,並且對數據庫的操做,無非就是四種:增刪改查。因此一個能提供增刪改查的通用類是必不可少的。這就是咱們常常所說的,通用數據庫訪問類(不少的程序員都喜歡把這個類命名爲SqlHelper,既然是名字,都是能夠隨意起的,只要不違反C#語法命名規範,固然這樣命名也是有好處,就是可使其餘程序員根據類的名稱,大概判斷出這個類是要幹什麼的)。

固然了,我此次作本身項目的時候,所寫的數據庫訪問類就沒有我上次看周金橋老師的書,而後模仿寫的數據庫訪問類那麼的複雜了(《【ASP.NET開發】ASP.NET對SQLServer的通用數據庫訪問類》)。固然了,我這裏的數據庫訪問類,主要仍是爲了簡介,和易用,只要知足我本身當前項目的須要就能夠了,不是每作一個項目,都要寫一個功能全面的數據庫訪問類。

代碼以下,請你們參考,更喜歡哪一個訪問類,本身能夠根據本身口味,或者須要,直接用也能夠:


  
  
  
  
  1. /// <summary>

  2. ///建立一個SqlHelper的數據庫訪問通用類,完成對數據庫的全部操做

  3. /// </summary>

  4. publicclass SqlHelper

  5. {

  6. //定義數據庫的鏈接字符串

  7. privatestaticreadonlystring connectionString = ConfigurationManager.ConnectionStrings["strConnectionString"].ConnectionString;

  8. /// <summary>

  9. /// 建立方法,完成對數據庫的非查詢的操做

  10. /// </summary>

  11. /// <param name="sql">sql語句</param>

  12. /// <param name="parameters">傳入的參數</param>

  13. /// <returns></returns>

  14. publicstaticint ExecuteNonQuery(string sql, params SqlParameter[] parameters)

  15.    {

  16. if (string.IsNullOrEmpty(sql))
           {

  17. using (SqlConnection con = new SqlConnection(connectionString))

  18.        {

  19.            con.Open();

  20. using (SqlCommand cmd = con.CreateCommand())

  21.            {

  22. try{

  23.                cmd.CommandText = sql;

  24.                cmd.Parameters.AddRange(parameters);

  25. string str = sql;

  26. return cmd.ExecuteNonQuery();

  27. }

  28. catch(Exception ex)
                       {
                           throw new Exception(ex.Message);
                       }

  29.            }

  30.        }

  31. else
           {
               return -1;
           }

  32.    }

  33. /// <summary>

  34. /// 完成查詢的結果值

  35. /// </summary>

  36. /// <param name="sql">sql語句</param>

  37. /// <param name="parameters">傳入的參數數組</param>

  38. /// <returns></returns>

  39. publicstaticint ExecuteScalar(string sql, params SqlParameter[] parameters)

  40.    {

  41. if (string.IsNullOrEmpty(sql))
           {


  42. using (SqlConnection con = new SqlConnection(connectionString))

  43.        {

  44.            con.Open();

  45. using (SqlCommand cmd = con.CreateCommand())

  46.            {

  47. try{

  48.                cmd.CommandText = sql;

  49.                cmd.Parameters.AddRange(parameters);

  50. return Convert.ToInt32( cmd.ExecuteScalar());

  51. }

  52. catch(Exception ex)
                       {
                           throw new Exception(ex.Message);
                       }

  53. }

  54.        }

  55. else
           {
               return -1;
           }

  56.    }

  57. /// <summary>

  58. /// 主要執行查詢操做

  59. /// </summary>

  60. /// <param name="sql">執行的sql語句</param>

  61. /// <param name="parameters">參數數組</param>

  62. /// <returns></returns>

  63. publicstatic DataTable ExecuteDataTable(string sql, params SqlParameter[] parameters)

  64.    {

  65. if (string.IsNullOrEmpty(sql))
           {


  66. using (SqlConnection con = new SqlConnection(connectionString))

  67.        {

  68.            con.Open();

  69. using (SqlCommand cmd = con.CreateCommand())

  70.            {

  71. try{

  72.                cmd.CommandText = sql;

  73.                cmd.Parameters.AddRange(parameters);

  74.                SqlDataAdapter adapter = new SqlDataAdapter(cmd);

  75.                DataTable dt = new DataTable();

  76.                adapter.Fill(dt);

  77. return dt;

  78. }

  79. catch(Exception ex)
                       {
                           throw new Exception(ex.Message);
                       }

  80.            }

  81.        }

  82.    }

  83. else
           {
               return -1;
           }

  84. }

這樣的類建立好之後,其餘的須要訪問數據庫的類,就能夠根據本身的須要,完成相應的增刪改查的操做了。仍是用一段代碼來演示吧:


  
  
  
  
  1. /// <summary>

  2. ///NewsDALL 的摘要說明

  3. /// </summary>

  4. publicclass NewsDALL

  5. {

  6. //向數據庫中插入新聞

  7. publicint AddNews(NewsModel model)

  8.    {

  9. string sql = "insert into News (name,author,time,content,sort,isdelete) values(@name,@author,@time,@content,@sort,@isdelete)";

  10. int nResult = SqlHelper.ExecuteNonQuery(sql, new SqlParameter("@name", model.StrNewsName), new SqlParameter("@author",model.StrNewsAuthor),new SqlParameter("@time", model.StrAddTime), new SqlParameter("@content", model.StrNewsContent), new SqlParameter("@sort", model.Sort), new SqlParameter("@isdelete", model.IsDelete1));

  11. return nResult;

  12.    }

  13. //執行數據庫的刪除操做

  14. publicint DeleteNew(int id)

  15.    {

  16. string sql = "delete from News where id=@id";

  17. int nResult = SqlHelper.ExecuteNonQuery(sql, new SqlParameter("@id", id));

  18. return nResult;

  19.    }

  20. //執行數據庫的更新操做

  21. publicint UpdateNew(NewsModel model, int nID)

  22.    {

  23. string sql = "update News set name=@name,time=@time,content=@content where id=" + nID;

  24. int nResult = SqlHelper.ExecuteNonQuery(sql, new SqlParameter("@name", model.StrNewsName), new SqlParameter("@time", model.StrAddTime), new SqlParameter("@content", model.StrNewsContent));

  25. return nResult;

  26.    }

  27. //執行數據庫的查詢操做

  28. public NewsModel GetNewsModel(int id)//聲明一次從數據庫中讀取新聞的條數

  29.    {

  30. string sql = "select * from News where id=@id";

  31.        DataTable dt = SqlHelper.ExecuteDataTable(sql, new SqlParameter("@id", id));

  32. if (dt.Rows.Count <= 0)

  33.        {

  34. returnnull;

  35.        }

  36. elseif (dt.Rows.Count == 1)

  37.        {

  38.            NewsModel newModel = new NewsModel();

  39.            DataRow dr = dt.Rows[0];

  40.            newModel.StrNewsName = dr["name"].ToString();

  41.            newModel.StrNewsAuthor = dr["author"].ToString();

  42.            newModel.StrAddTime = dr["time"].ToString();

  43.            newModel.StrNewsContent = dr["content"].ToString();

  44.            newModel.Sort = (int)dr["sort"];

  45. return newModel;

  46.        }

  47. else

  48.        {

  49. thrownew Exception("出現異常!");

  50.        }

  51.    }

  52. }


這裏的這個NewsDALL類,主要是來完成有關新聞須要對數據庫的各類操做,固然了,這只是這個類的一部分,主要是來演示NewsDALL類怎樣調用SqlHelper類中的方法,來完成對數據庫的操做的。

3)接下來就是最後一層,業務邏輯層了。

業務邏輯層的話主要來處理視圖層和數據庫訪問層之間的關係的。固然了,也能夠直接在視圖層調用數據庫訪問層,可是對於關係來講可能會增長複雜性,因此前輩們就專門的抽象出來一個業務邏輯層,把全部的業務邏輯關係都在這一層處理清楚以後再,訪問數據庫訪問層,進行對數據的操做。(固然這是我本身的理解,若是有什麼不對的話,請你們指正)

在我此次的項目中,貌似個人這一層徹底是多餘的,由於不須要什麼太多的業務邏輯的處理,能夠徹底在視圖層直接訪問數據庫訪問層的。

仍是使用代碼說話吧,固然這個仍然是NewsBLL類代碼的一部分:


  
  
  
  
  1. /// <summary>

  2. ///業務邏輯層主要處理視圖層和數據庫訪問直接的關係

  3. /// </summary>

  4. publicclass NewsBLL

  5. {

  6. //完成對數據庫的添加

  7. public int AddNew(NewsModel model)

  8.    {

  9.        NewsDALL newDALL = new NewsDALL();

  10. return newDALL.AddNews(model);

  11.    }

  12. //完成對數據的刪除

  13. public int DeleteNew(int i)

  14.    {

  15.        NewsDALL newDALL = new NewsDALL();

  16. return newDALL.DeleteNew(i);

  17.    }

  18. //返回一個新聞分類的對象

  19. public NewsModel GetModel(int intSort)

  20.    {

  21.        NewsModel model = new NewsModel();

  22. if (intSort == 1)

  23.        {

  24.            model.StrNewSort1 = "學院新聞";

  25.            model.StrNewSort2 = "";

  26.            model.StrNewSort3 = "";

  27.        }

  28. elseif (intSort == 2)

  29.        {

  30.            model.StrNewSort1 = "公告通知";

  31.            model.StrNewSort2 = "";

  32.            model.StrNewSort3 = "";

  33.        }

  34.        ..........

  35. return model;

  36.    }

  37. }


接下來就是在視圖層來經過訪問,業務邏輯層來和實體層,來玩成所須要的數據操做了。


仍是使用代碼來描述吧,這個代碼主要來完成對數據進行添加:


  
  
  
  
  1. publicvoid InsertData()

  2.   {

  3.       NewsModel newModel = new NewsModel();

  4.       newModel.StrNewsName = this.TextBox1.Text;

  5.       newModel.StrNewsAuthor = this.TxtBoxAuthor.Text;

  6.       newModel.StrAddTime = this.TxtDate.Text;

  7.       newModel.StrNewsContent = Server.HtmlDecode(FCKeditor1.Value);

  8.       newModel.Sort =Convert.ToInt32( this.DropDownList2.SelectedValue.ToString());

  9. //NewsBLL newBLL = new NewsBLL();

  10. int nResult= NewsBLL.AddNew(newModel);

  11. if (nResult != 0)

  12.       {

  13.           Response.Write("<script>alert('添加成功!')</script>");

  14.       }

  15. else

  16.       {

  17.           Response.Write("<script>alert('添加失敗!')</script>");

  18.       }

  19.   }


據我本身的理解,三層架構能夠算是一個團隊項目開發的基本框架,在這個框架的基礎上能夠知足一些設計模式的須要。固然能夠知足模塊開發的須要。

總結:

對於我此次的開發項目來講,收穫仍是不少的,之前僅僅是知道有三層架構這個東西,也看書,照着別人的代碼寫過,可是卻不能體會到這其中的真正意義。

優勢:①使代碼的重用更加的高了,不須要像之前作項目,每次在一個頁面反覆的編寫操做數據庫的代碼,而使用三層架構的話,只須要把注意力放在業務邏輯層     的業務邏輯的處理和數據庫訪問層的sql語句的編寫。

②代碼的整潔性,和易用性更加的高了。由於不一樣的操做都分別放在了不一樣的層,因此代碼邏輯更加清晰,若是作好註釋的話,別人可以更加清楚的理解    編寫者的意圖。

③可擴展型更加的高了,根據須要在不一樣的層編寫代碼,而後調用就能夠了。

④很是利於團隊開發。

固然了,三層架構的有點不只僅有這些,否則也不會成爲如今企業開發的基本框架,這只不過是我在開發中明顯的發現的優勢,拿出來跟你們分享一下。

缺點:①就是性能上確定比之前直接在相應的頁面編寫數據庫操做代碼上有點下降。可是這個徹底是能夠接受的,何況,對於我如今的水平就是代碼質量上可定還     有待提升,有更大的優化空間。

 ②就是在個人項目中,我以爲最大的浪費就是能夠在視圖層直接訪問數據庫訪問層,由於要處理的業務邏輯實在是很少,因此仍是有點代碼冗餘吧。因此,     之後仍是要跟據本身項目的須要,來靈活的使用,不必定要按照規定必須這樣作。

這僅僅是個人一點拙見,有什麼地方錯誤,請你們積極指正。也歡迎你們跟我交流。




原創做品,容許轉載,轉載時請務必以超連接形式標明文章 原始出處 、做者信息和本聲明。

相關文章
相關標籤/搜索