版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、<p> 淺談“三層結構”原理與用意</p><p> 2005年02月28日,AfritXia撰寫</p><p> 2006年12月28日,AfritXia第一次修改</p><p><b> 序</b></p><p> 在剛剛步入“多層結構”Web應用程序開發(fā)的時候,我閱讀過幾篇關于“asp.
2、net三層結構開發(fā)”的文章。但其多半都是對PetShop3.0和Duwamish7的局部剖析或者是學習筆記。對“三層結構”通體分析的學術文章幾乎沒有。</p><p> 2005年2月11日,Bincess BBS彬月論壇開始試運行。不久之后,我寫了一篇題目為《淺談“三層結構”原理與用意》的文章。舊版文章以彬月論壇程序中的部分代碼舉例,通過全局視角闡述了什么是“三層結構”的開發(fā)模式?為什么要這樣做?怎樣做?……
3、而在這篇文章的新作中,配合這篇文章我寫了7個程序實例(TraceLWord1~TraceLWord7留言板)以幫助讀者理解“三層結構”應用程序。這些程序示例可以在隨帶的CodePackage目錄中找到——</p><p> 對于那些有豐富經(jīng)驗的Web應用程序開發(fā)人員,他們認為文章寫的通俗易懂,很值得一讀。可是對于asp.net初學者,特別是沒有任何開發(fā)經(jīng)驗的人,文章閱讀起來就感到非常困難,不知文章所云。甚至有些
4、讀者對“三層結構”的認識更模糊了……</p><p> 關于“多層結構”開發(fā)模式,存在這樣一種爭議:一部分學者認為“多層結構”與“面向對象的程序設計思想”有著非常緊密的聯(lián)系。而另外一部分學者卻認為二者之間并無直接聯(lián)系。寫作這篇文章并不是要終結這種爭議,其行文目的是希望讀者能夠明白:在使用asp.net進行Web應用程序開發(fā)時,實現(xiàn)“多層結構”開發(fā)模式的方法、原理及用意。要順利的閱讀這篇文章,希望讀者能對“面向對
5、象的程序設計思想”有一定深度的認識,最好能懂一些“設計模式”的知識。如果你并不了解前面這些,那么這篇文章可能并不適合你現(xiàn)在閱讀。不過,無論這篇文章面對的讀者是誰,我都會盡量將文章寫好。我希望這篇文章能成為學習“三層結構”設計思想的經(jīng)典文章!</p><p> “三層結構”是什么?</p><p> “三層結構”一詞中的“三層”是指:“表現(xiàn)層”、“中間業(yè)務層”、“數(shù)據(jù)訪問層”。其中:&l
6、t;/p><p> 表 現(xiàn) 層:位于最外層(最上層),離用戶最近。用于顯示數(shù)據(jù)和接收用戶輸入的數(shù)據(jù),為用戶提供一種交互式操作的界面。</p><p> 中間業(yè)務層:負責處理用戶輸入的信息,或者是將這些信息發(fā)送給數(shù)據(jù)訪問層進行保存,或者是調(diào)用數(shù)據(jù)訪問層中的函數(shù)再次讀出這些數(shù)據(jù)。中間業(yè)務層也可以包括一些對“商業(yè)邏輯”描述代碼在里面。</p><p> 數(shù)據(jù)訪問層:僅實
7、現(xiàn)對數(shù)據(jù)的保存和讀取操作。數(shù)據(jù)訪問,可以訪問數(shù)據(jù)庫系統(tǒng)、二進制文件、文本文檔或是XML文檔。</p><p> 對依賴方向的研究將是本文的重點,數(shù)值返回方向基本上是沒有變化的。</p><p> 為什么需要 “三層結構”?——通常的設計方式</p><p> 在一個大型的Web應用程序中,如果不分以層次,那么在將來的升級維護中會遇到很大的麻煩。但在這篇文章里我
8、只想以一個簡單的留言板程序為示例,說明通常設計方式的不足——</p><p><b> 功能說明:</b></p><p> ListLWord.aspx(后臺程序文件 ListLWord.aspx.cs)列表顯示數(shù)據(jù)庫中的每條留言。</p><p> PostLWord.aspx(后臺程序文件 PostLWord.aspx.cs)發(fā)送留
9、言到數(shù)據(jù)庫。</p><p> 更完整的示例代碼,可以到CodePackage/TraceLWord1目錄中找到。數(shù)據(jù)庫中,僅含有一張數(shù)據(jù)表,其結構如下:</p><p> ListLWord.aspx 頁面文件(列表顯示留言)</p><p> #001 <%@ Page language="c#" Codebehind="
10、;ListLWord.aspx.cs" AutoEventWireup="false" </p><p> Inherits="TraceLWord1.ListLWord" %></p><p> #002 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transition
11、al//EN"></p><p><b> #003 </b></p><p> #004 <html></p><p> #005 <head></p><p> #006 <title>ListLWord</title></p>&
12、lt;p> #007 <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1"></p><p> #008 <meta name="CODE_LANGUAGE" Content="C#"></p><p&g
13、t; #009 <meta name=vs_defaultClientScript content="JavaScript"></p><p> #010 <meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5"></p>&
14、lt;p> #011 </head></p><p> #012 <body MS_POSITIONING="GridLayout"></p><p><b> #013 </b></p><p> #014 <form id="__aspNetForm" me
15、thod="post" runat="server"></p><p><b> #015 </b></p><p> #016 <a href="PostLWord.aspx">發(fā)送新留言</a></p><p><b> #017 &l
16、t;/b></p><p> #018 <asp:DataList ID="m_lwordListCtrl" Runat="Server"></p><p> #019 <ItemTemplate></p><p> #020 <div></p><p>
17、; #021 <%# DataBinder.Eval(Container.DataItem, "PostTime") %></p><p> #022 <%# DataBinder.Eval(Container.DataItem, "TextContent") %></p><p> #023 </div
18、></p><p> #024 </ItemTemplate></p><p> #025 </asp:DataList></p><p><b> #026 </b></p><p> #027 </form></p><p><b>
19、 #028 </b></p><p> #029 </body></p><p> #030 </html></p><p> 以最普通的設計方式制作留言板,效率很高。</p><p> 這些代碼可以在Visual Studio.NET 2003開發(fā)環(huán)境的設計視圖中快速建立。ListLWord.a
20、spx 后臺程序文件 ListLWord.aspx.cs</p><p> #001 using System;</p><p> #002 using System.Collections;</p><p> #003 using System.ComponentModel;</p><p> #004 using System.D
21、ata;</p><p> #005 using System.Data.OleDb;// 需要操作 Access 數(shù)據(jù)庫</p><p> #006 using System.Drawing;</p><p> #007 using System.Web;</p><p> #008 using System.Web.Sessio
22、nState;</p><p> #009 using System.Web.UI;</p><p> #010 using System.Web.UI.WebControls;</p><p> #011 using System.Web.UI.HtmlControls;</p><p><b> #012 </b&
23、gt;</p><p> #013 namespace TraceLWord1</p><p><b> #014 {</b></p><p> #015 /// <summary></p><p> #016 /// ListLWord 列表留言板信息</p><p>
24、 #017 /// </summary></p><p> #018 public class ListLWord : System.Web.UI.Page</p><p><b> #019 {</b></p><p> #020 // 留言列表控件</p><p> #021 pro
25、tected System.Web.UI.WebControls.DataList m_lwordListCtrl;</p><p><b> #022 </b></p><p> #023 /// <summary></p><p> #024 /// ListLWord.aspx 頁面加載函數(shù)</p>
26、<p> #025 /// </summary></p><p> #026 private void Page_Load(object sender, System.EventArgs e)</p><p><b> #027 {</b></p><p> #028 LWord_DataBin
27、d();</p><p><b> #029 }</b></p><p><b> #030 </b></p><p> #031 #region Web 窗體設計器生成的代碼</p><p> #032 override protected void OnInit(EventA
28、rgs e)</p><p><b> #033 {</b></p><p> #034 InitializeComponent();</p><p> #035 base.OnInit(e);</p><p><b> #036 }</b></p><
29、;p><b> #037 </b></p><p> #038 private void InitializeComponent()</p><p> #039 { </p><p> #040 this.Load+=new System.EventHandler(this.Page_Load);</p&
30、gt;<p><b> #041 }</b></p><p> #042 #endregion</p><p><b> #043 </b></p><p> #044 /// <summary></p><p> #045 /// 綁定留言信息列
31、表</p><p> #046 /// </summary></p><p> #047 private void LWord_DataBind()</p><p><b> #048 {</b></p><p> #049 string mdbConn=@"PROVIDE
32、R=Microsoft.Jet.OLEDB.4.0; </p><p> DATA Source=C:\DbFs\TraceLWordDb.mdb";</p><p> #050 string cmdText=@"SELECT * FROM [LWord] ORDER BY [LWordID] DESC";</p><p>&
33、lt;b> #051 </b></p><p> #052 OleDbConnection dbConn=new OleDbConnection(mdbConn);</p><p> #053 OleDbDataAdapter dbAdp=new OleDbDataAdapter(cmdText, dbConn);</p><p>
34、;<b> #054 </b></p><p> #055 DataSet ds=new DataSet();</p><p> #056 dbAdp.Fill(ds, @"LWordTable");</p><p><b> #057 </b></p><p&g
35、t; #058 m_lwordListCtrl.DataSource=ds.Tables[@"LWordTable"].DefaultView;</p><p> #059 m_lwordListCtrl.DataBind();</p><p><b> #060 }</b></p><p><b
36、> #061 }</b></p><p><b> #062 }</b></p><p> PostLWord.aspx頁面文件(發(fā)送留言到數(shù)據(jù)庫)</p><p> #001 <%@ Page language="c#" Codebehind="PostLWord.aspx.cs
37、" AutoEventWireup="false" </p><p> Inherits="TraceLWord1.PostLWord" %></p><p> #002 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">&l
38、t;/p><p><b> #003 </b></p><p> #004 <html></p><p> #005 <head></p><p> #006 <title>PostLWord</title></p><p> #007 <
39、;meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1"></p><p> #008 <meta name="CODE_LANGUAGE" Content="C#"></p><p> #009 <meta
40、name=vs_defaultClientScript content="JavaScript"></p><p> #010 <meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5"></p><p> #011 <
41、;/head></p><p> #012 <body MS_POSITIONING="GridLayout"></p><p><b> #013 </b></p><p> #014 <form id="__aspNetForm" method="post&qu
42、ot; runat="server"></p><p><b> #015 </b></p><p> #016 <textarea id="m_txtContent" runat="Server" rows=8 cols=48></textarea></p>
43、<p> #017 <input type="Button" id="m_btnPost" runat="Server" value="發(fā)送留言" /></p><p><b> #018 </b></p><p> #019 </form><
44、/p><p><b> #020 </b></p><p> #021 </body></p><p> #022 </html></p><p> PostLWord.aspx后臺程序文件PostLWord.aspx.cs</p><p> #001 using S
45、ystem;</p><p> #002 using System.Collections;</p><p> #003 using System.ComponentModel;</p><p> #004 using System.Data;</p><p> #005 using System.Data.OleDb;// 需要操
46、作 Access 數(shù)據(jù)庫</p><p> #006 using System.Drawing;</p><p> #007 using System.Web;</p><p> #008 using System.Web.SessionState;</p><p> #009 using System.Web.UI;</p&g
47、t;<p> #010 using System.Web.UI.WebControls;</p><p> #011 using System.Web.UI.HtmlControls;</p><p><b> #012 </b></p><p> #013 namespace TraceLWord1</p>
48、<p><b> #014 {</b></p><p> #015 /// <summary></p><p> #016 /// PostLWord 發(fā)送留言到數(shù)據(jù)庫</p><p> #017 /// </summary></p><p> #018 public
49、 class PostLWord : System.Web.UI.Page</p><p><b> #019 {</b></p><p> #020 // 留言內(nèi)容編輯框</p><p> #021 protected System.Web.UI.HtmlControls.HtmlTextArea m_txtContent;&
50、lt;/p><p> #022 // 提交按鈕</p><p> #023 protected System.Web.UI.HtmlControls.HtmlInputButton m_btnPost;</p><p><b> #024 </b></p><p> #025 /// <summar
51、y></p><p> #026 /// PostLWord.aspx 頁面加載函數(shù)</p><p> #027 /// </summary></p><p> #028 private void Page_Load(object sender, System.EventArgs e)</p><p>&l
52、t;b> #029 {</b></p><p><b> #030 }</b></p><p><b> #031 </b></p><p> #032 #region Web 窗體設計器生成的代碼</p><p> #033 override prote
53、cted void OnInit(EventArgs e)</p><p><b> #034 {</b></p><p> #035 InitializeComponent();</p><p> #036 base.OnInit(e);</p><p><b> #037 }&l
54、t;/b></p><p><b> #038 </b></p><p> #039 private void InitializeComponent()</p><p> #040 { </p><p> #041 this.Load+=new System.EventHandler(
55、this.Page_Load);</p><p> #042 this.m_btnPost.ServerClick+=new EventHandler(Post_ServerClick);</p><p><b> #043 }</b></p><p> #044 #endregion</p><p>
56、; #046 /// <summary></p><p> #047 /// 發(fā)送留言信息到數(shù)據(jù)庫</p><p> #048 /// </summary></p><p> #049 private void Post_ServerClick(object sender, EventArgs e)</p>
57、<p><b> #050 {</b></p><p> #051 // 獲取留言內(nèi)容</p><p> #052 string textContent=this.m_txtContent.Value;</p><p><b> #053 </b></p><p&g
58、t; #054 // 留言內(nèi)容不能為空</p><p> #055 if(textContent=="")</p><p> #056 throw new Exception("留言內(nèi)容為空");</p><p><b> #057 </b></p><p&
59、gt; #058 string mdbConn=@"PROVIDER=Microsoft.Jet.OLEDB.4.0; DATA Source=C:\DbFs\TraceLWordDb.mdb";</p><p> #059 string cmdText="INSERT INTO [LWord]([TextContent]) VALUES(@TextContent)&
60、quot;;</p><p><b> #060 </b></p><p> #061 OleDbConnection dbConn=new OleDbConnection(mdbConn);</p><p> #062 OleDbCommand dbCmd=new OleDbCommand(cmdText, dbConn);
61、</p><p><b> #063 </b></p><p> #064 // 設置留言內(nèi)容</p><p> #065 dbCmd.Parameters.Add(new OleDbParameter("@TextContent", </p><p> OleDbType.Lon
62、gVarWChar));</p><p> #066 dbCmd.Parameters["@TextContent"].Value=textContent;</p><p><b> #067 </b></p><p> #068 try</p><p><b> #06
63、9 {</b></p><p> #070 dbConn.Open();</p><p> #071 dbCmd.ExecuteNonQuery();</p><p><b> #072 }</b></p><p> #073 catch</p><
64、;p><b> #074 {</b></p><p> #075 throw;</p><p><b> #076 }</b></p><p> #077 finally</p><p><b> #078 {</b></p
65、><p> #079 dbConn.Close();</p><p><b> #080 }</b></p><p><b> #081 </b></p><p> #082 // 跳轉到留言顯示頁面</p><p> #083 Respons
66、e.Redirect("ListLWord.aspx", true);</p><p><b> #084 }</b></p><p><b> #085 }</b></p><p><b> #086 }</b></p><p> 僅僅通過兩
67、個頁面,就完成了一個基于Access數(shù)據(jù)庫的留言功能。</p><p> 程序并不算復雜,非常簡單清楚。但是隨后你會意識到其存在著不靈活性!</p><p> 為什么需要“三層結構”?——數(shù)據(jù)庫升遷、應用程序變化所帶來的問題</p><p> 留言板正式投入使用!但沒過多久,我準備把這個留言板程序的數(shù)據(jù)庫升遷到Microsoft SQL Server 2000
68、服務器上去!除了要把數(shù)據(jù)導入到SQL Server 2000中,還得修改相應的.aspx.cs程序文件。也就是說需要把調(diào)用OleDbConnection的地方修改成SqlConnection,還要把調(diào)用OleDbAdapter的地方,修改成SqlAdapter。雖然這并不是一件很困難的事情,因為整個站點非常小,僅僅只有兩個程序文件,所以修改起來并不費勁。但是,如果對于一個大型的商業(yè)網(wǎng)站,訪問數(shù)據(jù)庫的頁面有很多很多,如果以此方法一個頁面一
69、個頁面地進行修改,那么費時又費力!只是修改了一下數(shù)據(jù)庫,卻可能要修改上千張網(wǎng)頁。一動百動,這也許就是程序的一種不靈活性……</p><p> 再假如,我想給留言板加一個限制:</p><p> 每天上午09時之后到11時之前可以留言,下午則是13時之后到17時之前可以留言</p><p> 如果當天留言個數(shù)小于 40,則可以繼續(xù)留言</p>&l
70、t;p> 那么就需要把相應的代碼,添加到PostLWord.aspx.cs程序文件中。但是過了一段時間,我又希望去除這個限制,那么還要修改PostLWord.aspx.cs文件。但是,對于一個大型的商業(yè)網(wǎng)站,類似于這樣的限制,或者稱為“商業(yè)規(guī)則”,復雜又繁瑣。而且這些規(guī)則很容易隨著商家的意志為轉移。如果這些規(guī)則限制被分散到各個頁面中,那么規(guī)則一旦變化,就要修改很多的頁面!只是修改了一下規(guī)則限制,卻又可能要修改上千張網(wǎng)頁。一動百動
71、,這也許又是程序的一種不靈活性……</p><p> 最后,留言板使用過一段時間之后,出于某種目的,我希望把它修改成可以在本地運行的Windows程序,而放棄原來的Web型式。那么對于這個留言板,可以說是“滅頂之災”。所有代碼都要重新寫……當然這個例子比較極端,在現(xiàn)實中,這樣的情況還是很少會發(fā)生的——</p><p> 為什么需要“三層結構”?——初探,就從數(shù)據(jù)庫的升遷開始</p
72、><p> 一個站點中,訪問數(shù)據(jù)庫的程序代碼散落在各個頁面中,就像夜空中的星星一樣繁多。這樣一動百動的維護,難度可想而知。最難以忍受的是,對這種維護工作的投入,是沒有任何價值的……</p><p> 有一個比較好的解決辦法,那就是將訪問數(shù)據(jù)庫的代碼全部都放在一個程序文件里。這樣,數(shù)據(jù)庫平臺一旦發(fā)生變化,那么只需要集中修改這一個文件就可以了。我想有點開發(fā)經(jīng)驗的人,都會想到這一步的。這種“以不
73、變應萬變”的做法其實是簡單的“門面模式”的應用。如果把一個網(wǎng)站比喻成一家大飯店,那么“門面模式”中的“門面”,就像是飯店的服務生,而一個網(wǎng)站的瀏覽者,就像是一個來賓。來賓只需要發(fā)送命令給服務生,然后服務生就會按照命令辦事。至于服務生經(jīng)歷了多少辛苦才把事情辦成?那個并不是來賓感興趣的事情,來賓們只要求服務生盡快把自己交待事情辦完。我們就把ListLWord.aspx.cs程序就看成是一個來賓發(fā)出的命令,而把新加入的LWordTask.cs
74、程序看成是一個飯店服務生,那么來賓發(fā)出的命令就是:</p><p> “給我讀出留言板數(shù)據(jù)庫中的數(shù)據(jù),填充到DataSet數(shù)據(jù)集中并顯示出來!”</p><p> 而服務生接到命令后,就會依照執(zhí)行。而PostLWord.aspx.cs程序,讓服務生做的是:</p><p> “把我的留言內(nèi)容寫入到數(shù)據(jù)庫中!”</p><p> 而服務
75、生接到命令后,就會依照執(zhí)行。這就是TraceLWord2!可以在CodePackage/TraceLWord2目錄中找到——</p><p> 把所有的有關數(shù)據(jù)訪問的代碼都放到LWordTask.cs文件里,LWordTask.cs程序文件如下:</p><p> #001 using System;</p><p> #002 using System.Da
76、ta;</p><p> #003 using System.Data.OleDb;// 需要操作 Access 數(shù)據(jù)庫</p><p> #004 using System.Web;</p><p><b> #005 </b></p><p> #006 namespace TraceLWord2</
77、p><p><b> #007 {</b></p><p> #008 /// <summary></p><p> #009 /// LWordTask 數(shù)據(jù)庫任務類</p><p> #010 /// </summary></p><p> #011 pu
78、blic class LWordTask</p><p><b> #012 {</b></p><p> #013 // 數(shù)據(jù)庫連接字符串</p><p> #014 private const string DB_CONN=@"PROVIDER=Microsoft.Jet.OLEDB.4.0; </p>
79、<p> DATA Source=C:\DbFs\TraceLWordDb.mdb";</p><p><b> #015 </b></p><p> #016/// <summary></p><p> #017 /// 讀取數(shù)據(jù)庫表 LWord,并填充 DataSet 數(shù)據(jù)集</p&
80、gt;<p> #018 /// </summary></p><p> #019 /// <param name="ds">填充目標數(shù)據(jù)集</param></p><p> #020 /// <param name="tableName">表名稱</param&g
81、t;</p><p> #021 /// <returns>記錄行數(shù)</returns></p><p> #022 public int ListLWord(DataSet ds, string tableName)</p><p><b> #023 {</b></p><p&g
82、t; #024 string cmdText="SELECT * FROM [LWord] ORDER BY [LWordID] DESC";</p><p><b> #025 </b></p><p> #026 OleDbConnection dbConn=new OleDbConnection(DB_CONN);</
83、p><p> #027 OleDbDataAdapter dbAdp=new OleDbDataAdapter(cmdText, dbConn);</p><p><b> #028 </b></p><p> #029 int count=dbAdp.Fill(ds, tableName);</p><p&g
84、t;<b> #030 </b></p><p> #031 return count;</p><p><b> #032 }</b></p><p><b> #033 </b></p><p> #034 /// <summary>&l
85、t;/p><p> #035 /// 發(fā)送留言信息到數(shù)據(jù)庫</p><p> #036 /// </summary></p><p> #037 /// <param name="textContent">留言內(nèi)容</param></p><p> #038 publ
86、ic void PostLWord(string textContent)</p><p><b> #039 {</b></p><p> #040 // 留言內(nèi)容不能為空</p><p> #041 if(textContent==null || textContent=="")</p>
87、<p> #042 throw new Exception("留言內(nèi)容為空");</p><p><b> #043 </b></p><p> #044 string cmdText="INSERT INTO [LWord]([TextContent]) VALUES(@TextContent)&quo
88、t;;</p><p><b> #045 </b></p><p> #046 OleDbConnection dbConn=new OleDbConnection(DB_CONN);</p><p> #047 OleDbCommand dbCmd=new OleDbCommand(cmdText, dbConn);<
89、;/p><p><b> #048 </b></p><p> #049 // 設置留言內(nèi)容</p><p> #050 dbCmd.Parameters.Add(new OleDbParameter("@TextContent", OleDbType.LongVarWChar));</p>&l
90、t;p> #051 dbCmd.Parameters["@TextContent"].Value=textContent;</p><p><b> #052 </b></p><p> #053 try</p><p><b> #054 {</b></p>
91、<p> #055 dbConn.Open();</p><p> #056 dbCmd.ExecuteNonQuery();</p><p><b> #057 }</b></p><p> #058 catch</p><p><b> #059 {
92、</b></p><p> #060 throw;</p><p><b> #061 }</b></p><p> #062 finally</p><p><b> #063 {</b></p><p> #064
93、dbConn.Close();</p><p><b> #065 }</b></p><p><b> #066 }</b></p><p><b> #067 }</b></p><p><b> #068 }</b></p&
94、gt;<p> 如果將數(shù)據(jù)庫從Access 2000修改為SQL Server 2000,那么只需要修改LWordTask.cs這一個文件。如果LWordTask.cs文件太大,也可以把它切割成幾個文件或“類”。如果被切割成的“類”還是很多,也可以把這些訪問數(shù)據(jù)庫的類放到一個新建的“項目”里。當然,原來的ListLWord.aspx.cs文件應該作以修改,LWord_DataBind函數(shù)被修改成:</p>
95、<p><b> ...</b></p><p> #046 private void LWord_DataBind()</p><p><b> #047 {</b></p><p> #048 DataSet ds=new DataSet();</p><p>
96、 #049 (new LWordTask()).ListLWord(ds, @"LWordTable");</p><p><b> #050 </b></p><p> #051 m_lwordListCtrl.DataSource=ds.Tables[@"LWordTable"].DefaultView;&l
97、t;/p><p> #052 m_lwordListCtrl.DataBind();</p><p><b> #053 }</b></p><p><b> ...</b></p><p> 原來的PostLWord.aspx.cs文件也應作以修改,Post_ServerClick函
98、數(shù)被修改成:</p><p><b> ...</b></p><p> #048 private void Post_ServerClick(object sender, EventArgs e)</p><p><b> #049 {</b></p><p> #050 /
99、/ 獲取留言內(nèi)容</p><p> #051 string textContent=this.m_txtContent.Value;</p><p><b> #052 </b></p><p> #053 (new LWordTask()).PostLWord(textContent);</p><p&g
100、t;<b> #054 </b></p><p> #055 // 跳轉到留言顯示頁面</p><p> #056 Response.Redirect("ListLWord.aspx", true);</p><p><b> #057 }</b></p><
101、p><b> ...</b></p><p> 從前面的程序段中可以看出,ListLWord.aspx.cs和PostLWord.aspx.cs這兩個文件已經(jīng)找不到和數(shù)據(jù)庫相關的代碼了。只看到一些和LWordTask類有關系的代碼,這就符合了“設計模式”中的一種重要原則:“迪米特法則”。“迪米特法則”主要是說:讓一個“類”與盡量少的其它的類發(fā)生關系。在TraceLWord1中,Li
102、stLWord.aspx.cs這個類和OleDbConnection及OleDbDataAdapter都發(fā)生了關系,所以它破壞了“迪米特法則”。利用一個“中間人”是“迪米特法則”解決問題的辦法,這也是“門面模式”必須遵循的原則。下面就引出這個LWordTask門面類的示意圖:</p><p> ListLWord.aspx.cs和PostLWord.aspx.cs兩個文件對數(shù)據(jù)庫的訪問,全部委托LWordTas
103、k類這個“中間人”來辦理。利用“門面模式”,將頁面類和數(shù)據(jù)庫類進行隔離。這樣就作到了頁面類不依賴于數(shù)據(jù)庫的效果。以一段比較簡單的代碼來描述這三個程序的關系:</p><p> public class ListLWord</p><p><b> {</b></p><p> private void LWord_DataBind()&l
104、t;/p><p><b> {</b></p><p> (new LWordTask()).ListLWord( ... );</p><p><b> }</b></p><p><b> }</b></p><p> public class
105、 PostLWord</p><p><b> {</b></p><p> private void Post_ServerClick(object sender, EventArgs e)</p><p><b> {</b></p><p> (new LWordTask()).Pos
106、tLWord( ... );</p><p><b> }</b></p><p><b> }</b></p><p> public class LWordTask</p><p><b> {</b></p><p> public Da
107、taSet ListLWord(DataSet ds)...</p><p> public void PostLWord(string textContent)...</p><p><b> }</b></p><p> 應用中間業(yè)務層,實現(xiàn)“三層結構”</p><p> 前面這種分離數(shù)據(jù)訪問代碼的形式,可以
108、說是一種“三層結構”的簡化形式。因為它沒有“中間業(yè)務層”也可以稱呼它為“二層結構”。一個真正的“三層”程序,是要有“中間業(yè)務層”的,而它的作用是連接“外觀層”和“數(shù)據(jù)訪問層”。換句話說:“外觀層”的任務先委托給“中間業(yè)務層”來辦理,然后“中間業(yè)務層”再去委托“數(shù)據(jù)訪問層”來辦理……</p><p> 那么為什么要應用“中間業(yè)務層”呢?“中間業(yè)務層”的用途有很多,例如:驗證用戶輸入數(shù)據(jù)、緩存從數(shù)據(jù)庫中讀取的數(shù)據(jù)等
109、等……但是,“中間業(yè)務層”的實際目的是將“數(shù)據(jù)訪問層”的最基礎的存儲邏輯組合起來,形成一種業(yè)務規(guī)則。例如:“在一個購物網(wǎng)站中有這樣的一個規(guī)則:在該網(wǎng)站第一次購物的用戶,系統(tǒng)為其自動注冊”。這樣的業(yè)務邏輯放在中間層最合適:</p><p> 在“數(shù)據(jù)訪問層”中,最好不要出現(xiàn)任何“業(yè)務邏輯”!也就是說,要保證“數(shù)據(jù)訪問層”的中的函數(shù)功能的原子性!即最小性和不可再分?!皵?shù)據(jù)訪問層”只管負責存儲或讀取數(shù)據(jù)就可以了。&l
110、t;/p><p> 在新TraceLWord3中,應用了“企業(yè)級模板項目”。把原來的LWordTask.cs,并放置到一個單一的項目里,項目名稱為:AccessTask。解決方案中又新建了一個名稱為:InterService的項目,該項目中包含一個LWordService.cs程序文件,它便是“中間業(yè)務層”程序。為了不重復命名,TraceLWord3的網(wǎng)站被放置到了WebUI項目中。更完整的代碼,可以在CodePa
111、ckage/TraceLWord3目錄中找到——</p><p> 這些類的關系,也可以表示為如下的示意圖:</p><p> LWordService.cs程序源碼:</p><p> #001 using System;</p><p> #002 using System.Data;</p><p>&l
112、t;b> #003 </b></p><p> #004 using TraceLWord3.AccessTask;// 引用數(shù)據(jù)訪問層</p><p><b> #005 </b></p><p> #006 namespace TraceLWord3.InterService</p><p&
113、gt;<b> #007 {</b></p><p> #008 /// <summary></p><p> #009 /// LWordService 留言板服務類</p><p> #010 /// </summary></p><p> #011 public class
114、 LWordService</p><p><b> #012 {</b></p><p> #013 /// <summary></p><p> #014 /// 讀取數(shù)據(jù)庫表 LWord,并填充 DataSet 數(shù)據(jù)集</p><p> #015 /// </summary&
115、gt;</p><p> #016 /// <param name="ds">填充目標數(shù)據(jù)集</param></p><p> #017 /// <param name="tableName">表名稱</param></p><p> #018 /// <
116、returns>記錄行數(shù)</returns></p><p> #019 public int ListLWord(DataSet ds, string tableName)</p><p><b> #020 {</b></p><p> #021 return (new LWordTask()).Lis
117、tLWord(ds, tableName);</p><p><b> #022 }</b></p><p><b> #023 </b></p><p> #024 /// <summary></p><p> #025 /// 發(fā)送留言信息到數(shù)據(jù)庫</p&g
118、t;<p> #026 /// </summary></p><p> #027 /// <param name="textContent">留言內(nèi)容</param></p><p> #028 public void PostLWord(string content)</p><p
119、><b> #029 {</b></p><p> #030 (new LWordTask()).PostLWord(content);</p><p><b> #031 }</b></p><p><b> #032 }</b></p><p>
120、;<b> #033 }</b></p><p> 從LWordService.cs程序文件的行#021和行#030可以看出,“中間業(yè)務層”并沒有實現(xiàn)什么業(yè)務邏輯,只是簡單的調(diào)用了“數(shù)據(jù)訪問層”的類方法……這樣做是為了讓讀者更直觀的看明白“三層結構”應用程序的調(diào)用順序,看清楚它的全貌。加入了“中間業(yè)務層”,那么原來的ListLWord.aspx.cs文件應該作以修改:</p>
121、<p><b> ...</b></p><p> #012 using TraceLWord3.InterService;// 引用中間服務層</p><p><b> ...</b></p><p> #045 /// <summary></p><p>
122、; #046 /// 綁定留言信息列表</p><p> #047 /// </summary></p><p> #048 private void LWord_DataBind()</p><p><b> #049 {</b></p><p> #050 DataSet
123、ds=new DataSet();</p><p> #051 (new LWordService()).ListLWord(ds, @"LWordTable");</p><p><b> #052 </b></p><p> #053 m_lwordListCtrl.DataSource=ds.Tabl
124、es[@"LWordTable"].DefaultView;</p><p> #054 m_lwordListCtrl.DataBind();</p><p><b> #055 }</b></p><p><b> ...</b></p><p> 原來的P
125、ostLWord.aspx.cs文件也應作以修改:</p><p><b> ...</b></p><p> #012 using TraceLWord3.InterService;// 引用中間服務層</p><p><b> ...</b></p><p> #047 ///
126、<summary></p><p> #048 /// 發(fā)送留言到數(shù)據(jù)庫</p><p> #049 /// </summary></p><p> #050 private void Post_ServerClick(object sender, EventArgs e)</p><p><b
127、> #051 {</b></p><p> #052 // 獲取留言內(nèi)容</p><p> #053 string textContent=this.m_txtContent.Value;</p><p><b> #054 </b></p><p> #055 (new
128、 LWordService()).PostLWord(textContent);</p><p><b> #056 </b></p><p> #057 // 跳轉到留言顯示頁面</p><p> #058 Response.Redirect("ListLWord.aspx", true);</p&
129、gt;<p><b> #059 }</b></p><p><b> ...</b></p><p> 到目前為止,TraceLWord3程序已經(jīng)是一個簡單的“三層結構”的應用程序,以一段比較簡單的代碼來描述四個程序的關系:</p><p> namespace TraceLWord3.WebL
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 淺談三層結構的原理與用意
- 三層結構實例
- 企業(yè)文化的三層結構
- 三層結構人才測評系統(tǒng)的研究與實現(xiàn).pdf
- 三層立體車庫結構與PLC設計.dwg
- 三層立體車庫結構與PLC設計.dwg
- 三層立體車庫結構與PLC設計.dwg
- 三層立體車庫結構與PLC設計.doc
- 三層結構與商業(yè)自動化系統(tǒng).pdf
- 三層立體車庫結構與PLC設計.dwg
- 三層立體車庫結構與PLC設計.dwg
- 三層立體車庫結構與PLC設計.dwg
- 三層立體車庫結構與PLC設計.doc
- 三層構架
- 三層.dwg
- 三層.dwg
- 三層.dwg
- 三層別墅設計 三層別墅裝修效果
- 三層立體車庫結構與PLC設計.dwg
- 三層立體車庫結構與PLC設計.dwg
評論
0/150
提交評論