淺談“三層結(jié)構(gòu)”的原理與用意_第1頁
已閱讀1頁,還剩43頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、<p>  淺談“三層結(jié)構(gòu)”原理與用意</p><p>  2005年02月28日,AfritXia撰寫</p><p>  2006年12月28日,AfritXia第一次修改</p><p><b>  序</b></p><p>  在剛剛步入“多層結(jié)構(gòu)”Web應(yīng)用程序開發(fā)的時(shí)候,我閱讀過幾篇關(guān)于“asp.

2、net三層結(jié)構(gòu)開發(fā)”的文章。但其多半都是對(duì)PetShop3.0和Duwamish7的局部剖析或者是學(xué)習(xí)筆記。對(duì)“三層結(jié)構(gòu)”通體分析的學(xué)術(shù)文章幾乎沒有。</p><p>  2005年2月11日,Bincess BBS彬月論壇開始試運(yùn)行。不久之后,我寫了一篇題目為《淺談“三層結(jié)構(gòu)”原理與用意》的文章。舊版文章以彬月論壇程序中的部分代碼舉例,通過全局視角闡述了什么是“三層結(jié)構(gòu)”的開發(fā)模式?為什么要這樣做?怎樣做?……

3、而在這篇文章的新作中,配合這篇文章我寫了7個(gè)程序?qū)嵗═raceLWord1~TraceLWord7留言板)以幫助讀者理解“三層結(jié)構(gòu)”應(yīng)用程序。這些程序示例可以在隨帶的CodePackage目錄中找到——</p><p>  對(duì)于那些有豐富經(jīng)驗(yàn)的Web應(yīng)用程序開發(fā)人員,他們認(rèn)為文章寫的通俗易懂,很值得一讀??墒菍?duì)于asp.net初學(xué)者,特別是沒有任何開發(fā)經(jīng)驗(yàn)的人,文章閱讀起來就感到非常困難,不知文章所云。甚至有些

4、讀者對(duì)“三層結(jié)構(gòu)”的認(rèn)識(shí)更模糊了……</p><p>  關(guān)于“多層結(jié)構(gòu)”開發(fā)模式,存在這樣一種爭議:一部分學(xué)者認(rèn)為“多層結(jié)構(gòu)”與“面向?qū)ο蟮某绦蛟O(shè)計(jì)思想”有著非常緊密的聯(lián)系。而另外一部分學(xué)者卻認(rèn)為二者之間并無直接聯(lián)系。寫作這篇文章并不是要終結(jié)這種爭議,其行文目的是希望讀者能夠明白:在使用asp.net進(jìn)行Web應(yīng)用程序開發(fā)時(shí),實(shí)現(xiàn)“多層結(jié)構(gòu)”開發(fā)模式的方法、原理及用意。要順利的閱讀這篇文章,希望讀者能對(duì)“面向?qū)?/p>

5、象的程序設(shè)計(jì)思想”有一定深度的認(rèn)識(shí),最好能懂一些“設(shè)計(jì)模式”的知識(shí)。如果你并不了解前面這些,那么這篇文章可能并不適合你現(xiàn)在閱讀。不過,無論這篇文章面對(duì)的讀者是誰,我都會(huì)盡量將文章寫好。我希望這篇文章能成為學(xué)習(xí)“三層結(jié)構(gòu)”設(shè)計(jì)思想的經(jīng)典文章!</p><p>  “三層結(jié)構(gòu)”是什么?</p><p>  “三層結(jié)構(gòu)”一詞中的“三層”是指:“表現(xiàn)層”、“中間業(yè)務(wù)層”、“數(shù)據(jù)訪問層”。其中:&l

6、t;/p><p>  表 現(xiàn) 層:位于最外層(最上層),離用戶最近。用于顯示數(shù)據(jù)和接收用戶輸入的數(shù)據(jù),為用戶提供一種交互式操作的界面。</p><p>  中間業(yè)務(wù)層:負(fù)責(zé)處理用戶輸入的信息,或者是將這些信息發(fā)送給數(shù)據(jù)訪問層進(jìn)行保存,或者是調(diào)用數(shù)據(jù)訪問層中的函數(shù)再次讀出這些數(shù)據(jù)。中間業(yè)務(wù)層也可以包括一些對(duì)“商業(yè)邏輯”描述代碼在里面。</p><p>  數(shù)據(jù)訪問層:僅實(shí)

7、現(xiàn)對(duì)數(shù)據(jù)的保存和讀取操作。數(shù)據(jù)訪問,可以訪問數(shù)據(jù)庫系統(tǒng)、二進(jìn)制文件、文本文檔或是XML文檔。</p><p>  對(duì)依賴方向的研究將是本文的重點(diǎn),數(shù)值返回方向基本上是沒有變化的。</p><p>  為什么需要 “三層結(jié)構(gòu)”?——通常的設(shè)計(jì)方式</p><p>  在一個(gè)大型的Web應(yīng)用程序中,如果不分以層次,那么在將來的升級(jí)維護(hù)中會(huì)遇到很大的麻煩。但在這篇文章里我

8、只想以一個(gè)簡單的留言板程序?yàn)槭纠?,說明通常設(shè)計(jì)方式的不足——</p><p><b>  功能說明:</b></p><p>  ListLWord.aspx(后臺(tái)程序文件 ListLWord.aspx.cs)列表顯示數(shù)據(jù)庫中的每條留言。</p><p>  PostLWord.aspx(后臺(tái)程序文件 PostLWord.aspx.cs)發(fā)送留

9、言到數(shù)據(jù)庫。</p><p>  更完整的示例代碼,可以到CodePackage/TraceLWord1目錄中找到。數(shù)據(jù)庫中,僅含有一張數(shù)據(jù)表,其結(jié)構(gòu)如下:</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>  以最普通的設(shè)計(jì)方式制作留言板,效率很高。</p><p>  這些代碼可以在Visual Studio.NET 2003開發(fā)環(huán)境的設(shè)計(jì)視圖中快速建立。ListLWord.a

20、spx 后臺(tái)程序文件 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 窗體設(shè)計(jì)器生成的代碼</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后臺(tái)程序文件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 窗體設(shè)計(jì)器生成的代碼</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 // 設(shè)置留言內(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 // 跳轉(zhuǎn)到留言顯示頁面</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、個(gè)頁面,就完成了一個(gè)基于Access數(shù)據(jù)庫的留言功能。</p><p>  程序并不算復(fù)雜,非常簡單清楚。但是隨后你會(huì)意識(shí)到其存在著不靈活性!</p><p>  為什么需要“三層結(jié)構(gòu)”?——數(shù)據(jù)庫升遷、應(yīng)用程序變化所帶來的問題</p><p>  留言板正式投入使用!但沒過多久,我準(zhǔn)備把這個(gè)留言板程序的數(shù)據(jù)庫升遷到Microsoft SQL Server 2000

68、服務(wù)器上去!除了要把數(shù)據(jù)導(dǎo)入到SQL Server 2000中,還得修改相應(yīng)的.aspx.cs程序文件。也就是說需要把調(diào)用OleDbConnection的地方修改成SqlConnection,還要把調(diào)用OleDbAdapter的地方,修改成SqlAdapter。雖然這并不是一件很困難的事情,因?yàn)檎麄€(gè)站點(diǎn)非常小,僅僅只有兩個(gè)程序文件,所以修改起來并不費(fèi)勁。但是,如果對(duì)于一個(gè)大型的商業(yè)網(wǎng)站,訪問數(shù)據(jù)庫的頁面有很多很多,如果以此方法一個(gè)頁面一

69、個(gè)頁面地進(jìn)行修改,那么費(fèi)時(shí)又費(fèi)力!只是修改了一下數(shù)據(jù)庫,卻可能要修改上千張網(wǎng)頁。一動(dòng)百動(dòng),這也許就是程序的一種不靈活性……</p><p>  再假如,我想給留言板加一個(gè)限制:</p><p>  每天上午09時(shí)之后到11時(shí)之前可以留言,下午則是13時(shí)之后到17時(shí)之前可以留言</p><p>  如果當(dāng)天留言個(gè)數(shù)小于 40,則可以繼續(xù)留言</p>&l

70、t;p>  那么就需要把相應(yīng)的代碼,添加到PostLWord.aspx.cs程序文件中。但是過了一段時(shí)間,我又希望去除這個(gè)限制,那么還要修改PostLWord.aspx.cs文件。但是,對(duì)于一個(gè)大型的商業(yè)網(wǎng)站,類似于這樣的限制,或者稱為“商業(yè)規(guī)則”,復(fù)雜又繁瑣。而且這些規(guī)則很容易隨著商家的意志為轉(zhuǎn)移。如果這些規(guī)則限制被分散到各個(gè)頁面中,那么規(guī)則一旦變化,就要修改很多的頁面!只是修改了一下規(guī)則限制,卻又可能要修改上千張網(wǎng)頁。一動(dòng)百動(dòng)

71、,這也許又是程序的一種不靈活性……</p><p>  最后,留言板使用過一段時(shí)間之后,出于某種目的,我希望把它修改成可以在本地運(yùn)行的Windows程序,而放棄原來的Web型式。那么對(duì)于這個(gè)留言板,可以說是“滅頂之災(zāi)”。所有代碼都要重新寫……當(dāng)然這個(gè)例子比較極端,在現(xiàn)實(shí)中,這樣的情況還是很少會(huì)發(fā)生的——</p><p>  為什么需要“三層結(jié)構(gòu)”?——初探,就從數(shù)據(jù)庫的升遷開始</p

72、><p>  一個(gè)站點(diǎn)中,訪問數(shù)據(jù)庫的程序代碼散落在各個(gè)頁面中,就像夜空中的星星一樣繁多。這樣一動(dòng)百動(dòng)的維護(hù),難度可想而知。最難以忍受的是,對(duì)這種維護(hù)工作的投入,是沒有任何價(jià)值的……</p><p>  有一個(gè)比較好的解決辦法,那就是將訪問數(shù)據(jù)庫的代碼全部都放在一個(gè)程序文件里。這樣,數(shù)據(jù)庫平臺(tái)一旦發(fā)生變化,那么只需要集中修改這一個(gè)文件就可以了。我想有點(diǎn)開發(fā)經(jīng)驗(yàn)的人,都會(huì)想到這一步的。這種“以不

73、變應(yīng)萬變”的做法其實(shí)是簡單的“門面模式”的應(yīng)用。如果把一個(gè)網(wǎng)站比喻成一家大飯店,那么“門面模式”中的“門面”,就像是飯店的服務(wù)生,而一個(gè)網(wǎng)站的瀏覽者,就像是一個(gè)來賓。來賓只需要發(fā)送命令給服務(wù)生,然后服務(wù)生就會(huì)按照命令辦事。至于服務(wù)生經(jīng)歷了多少辛苦才把事情辦成?那個(gè)并不是來賓感興趣的事情,來賓們只要求服務(wù)生盡快把自己交待事情辦完。我們就把ListLWord.aspx.cs程序就看成是一個(gè)來賓發(fā)出的命令,而把新加入的LWordTask.cs

74、程序看成是一個(gè)飯店服務(wù)生,那么來賓發(fā)出的命令就是:</p><p>  “給我讀出留言板數(shù)據(jù)庫中的數(shù)據(jù),填充到DataSet數(shù)據(jù)集中并顯示出來!”</p><p>  而服務(wù)生接到命令后,就會(huì)依照?qǐng)?zhí)行。而PostLWord.aspx.cs程序,讓服務(wù)生做的是:</p><p>  “把我的留言內(nèi)容寫入到數(shù)據(jù)庫中!”</p><p>  而服務(wù)

75、生接到命令后,就會(huì)依照?qǐng)?zhí)行。這就是TraceLWord2!可以在CodePackage/TraceLWord2目錄中找到——</p><p>  把所有的有關(guān)數(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ù)庫任務(wù)類</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">填充目標(biāo)數(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 // 設(shè)置留言內(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這一個(gè)文件。如果LWordTask.cs文件太大,也可以把它切割成幾個(gè)文件或“類”。如果被切割成的“類”還是很多,也可以把這些訪問數(shù)據(jù)庫的類放到一個(gè)新建的“項(xiàng)目”里。當(dāng)然,原來的ListLWord.aspx.cs文件應(yīng)該作以修改,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文件也應(yīng)作以修改,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 // 跳轉(zhuǎn)到留言顯示頁面</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這兩個(gè)文件已經(jīng)找不到和數(shù)據(jù)庫相關(guān)的代碼了。只看到一些和LWordTask類有關(guān)系的代碼,這就符合了“設(shè)計(jì)模式”中的一種重要原則:“迪米特法則”。“迪米特法則”主要是說:讓一個(gè)“類”與盡量少的其它的類發(fā)生關(guān)系。在TraceLWord1中,Li

102、stLWord.aspx.cs這個(gè)類和OleDbConnection及OleDbDataAdapter都發(fā)生了關(guān)系,所以它破壞了“迪米特法則”。利用一個(gè)“中間人”是“迪米特法則”解決問題的辦法,這也是“門面模式”必須遵循的原則。下面就引出這個(gè)LWordTask門面類的示意圖:</p><p>  ListLWord.aspx.cs和PostLWord.aspx.cs兩個(gè)文件對(duì)數(shù)據(jù)庫的訪問,全部委托LWordTas

103、k類這個(gè)“中間人”來辦理。利用“門面模式”,將頁面類和數(shù)據(jù)庫類進(jìn)行隔離。這樣就作到了頁面類不依賴于數(shù)據(jù)庫的效果。以一段比較簡單的代碼來描述這三個(gè)程序的關(guān)系:</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īng)用中間業(yè)務(wù)層,實(shí)現(xiàn)“三層結(jié)構(gòu)”</p><p>  前面這種分離數(shù)據(jù)訪問代碼的形式,可以

108、說是一種“三層結(jié)構(gòu)”的簡化形式。因?yàn)樗鼪]有“中間業(yè)務(wù)層”也可以稱呼它為“二層結(jié)構(gòu)”。一個(gè)真正的“三層”程序,是要有“中間業(yè)務(wù)層”的,而它的作用是連接“外觀層”和“數(shù)據(jù)訪問層”。換句話說:“外觀層”的任務(wù)先委托給“中間業(yè)務(wù)層”來辦理,然后“中間業(yè)務(wù)層”再去委托“數(shù)據(jù)訪問層”來辦理……</p><p>  那么為什么要應(yīng)用“中間業(yè)務(wù)層”呢?“中間業(yè)務(wù)層”的用途有很多,例如:驗(yàn)證用戶輸入數(shù)據(jù)、緩存從數(shù)據(jù)庫中讀取的數(shù)據(jù)等

109、等……但是,“中間業(yè)務(wù)層”的實(shí)際目的是將“數(shù)據(jù)訪問層”的最基礎(chǔ)的存儲(chǔ)邏輯組合起來,形成一種業(yè)務(wù)規(guī)則。例如:“在一個(gè)購物網(wǎng)站中有這樣的一個(gè)規(guī)則:在該網(wǎng)站第一次購物的用戶,系統(tǒng)為其自動(dòng)注冊(cè)”。這樣的業(yè)務(wù)邏輯放在中間層最合適:</p><p>  在“數(shù)據(jù)訪問層”中,最好不要出現(xiàn)任何“業(yè)務(wù)邏輯”!也就是說,要保證“數(shù)據(jù)訪問層”的中的函數(shù)功能的原子性!即最小性和不可再分。“數(shù)據(jù)訪問層”只管負(fù)責(zé)存儲(chǔ)或讀取數(shù)據(jù)就可以了。&l

110、t;/p><p>  在新TraceLWord3中,應(yīng)用了“企業(yè)級(jí)模板項(xiàng)目”。把原來的LWordTask.cs,并放置到一個(gè)單一的項(xiàng)目里,項(xiàng)目名稱為:AccessTask。解決方案中又新建了一個(gè)名稱為:InterService的項(xiàng)目,該項(xiàng)目中包含一個(gè)LWordService.cs程序文件,它便是“中間業(yè)務(wù)層”程序。為了不重復(fù)命名,TraceLWord3的網(wǎng)站被放置到了WebUI項(xiàng)目中。更完整的代碼,可以在CodePa

111、ckage/TraceLWord3目錄中找到——</p><p>  這些類的關(guān)系,也可以表示為如下的示意圖:</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 留言板服務(wù)類</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">填充目標(biāo)數(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è)務(wù)層”并沒有實(shí)現(xiàn)什么業(yè)務(wù)邏輯,只是簡單的調(diào)用了“數(shù)據(jù)訪問層”的類方法……這樣做是為了讓讀者更直觀的看明白“三層結(jié)構(gòu)”應(yīng)用程序的調(diào)用順序,看清楚它的全貌。加入了“中間業(yè)務(wù)層”,那么原來的ListLWord.aspx.cs文件應(yīng)該作以修改:</p>

121、<p><b>  ...</b></p><p>  #012 using TraceLWord3.InterService;// 引用中間服務(wù)層</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文件也應(yīng)作以修改:</p><p><b>  ...</b></p><p>  #012 using TraceLWord3.InterService;// 引用中間服務(wù)層</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 // 跳轉(zhuǎn)到留言顯示頁面</p><p>  #058 Response.Redirect("ListLWord.aspx", true);</p&

129、gt;<p><b>  #059 }</b></p><p><b>  ...</b></p><p>  到目前為止,TraceLWord3程序已經(jīng)是一個(gè)簡單的“三層結(jié)構(gòu)”的應(yīng)用程序,以一段比較簡單的代碼來描述四個(gè)程序的關(guān)系:</p><p>  namespace TraceLWord3.WebL

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論