浅谈“三层结构”原理与用意
Download
1 / 1378

 浅谈“三层结构”原理与用意 - PowerPoint PPT Presentation


  • 127 Views
  • Uploaded on

 浅谈“三层结构”原理与用意. 浅谈“三层结构”原理与用意. 2005 年 02 月 28 日, AfritXia 撰写. 2006 年 12 月 28 日, AfritXia 第一次修改. 序. 在刚刚步入“多层结构” Web 应用程序开发的时候,我阅读过几篇关于“ asp.net 三层结构开发”的文章。但其多半都是对 PetShop3.0 和 Duwamish7 的局部剖析或者是学习笔记。对“三层结构”通体分析的学术文章几乎没有。.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about '  浅谈“三层结构”原理与用意' - diella


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript


2005 02 28 afritxia
2005年02月28日,AfritXia撰写


2006 12 28 afritxia
2006年12月28日,AfritXia第一次修改



Web asp net petshop3 0 duwamish7
在刚刚步入“多层结构”Web应用程序开发的时候,我阅读过几篇关于“asp.net三层结构开发”的文章。但其多半都是对PetShop3.0和Duwamish7的局部剖析或者是学习笔记。对“三层结构”通体分析的学术文章几乎没有。


2005年2月11日,Bincess BBS彬月论坛开始试运行。不久之后,我写了一篇题目为《浅谈“三层结构”原理与用意》的文章。旧版文章以彬月论坛程序中的部分代码举例,通过全局视角阐述了什么是“三层结构”的开发模式?为什么要这样做?怎样做?……而在这篇文章的新作中,配合这篇文章我写了7个程序实例(TraceLWord1~TraceLWord7留言板)以帮助读者理解“三层结构”应用程序。这些程序示例可以在随带的CodePackage目录中找到——


Web asp net
  对于那些有丰富经验的Web应用程序开发人员,他们认为文章写的通俗易懂,很值得一读。可是对于asp.net初学者,特别是没有任何开发经验的人,文章阅读起来就感到非常困难,不知文章所云。甚至有些读者对“三层结构”的认识更模糊了……


  关于“多层结构”开发模式,存在这样一种争议:一部分学者认为“多层结构”与“面向对象的程序设计思想”有着非常紧密的联系。而另外一部分学者却认为二者之间并无直接联系。写作这篇文章并不是要终结这种争议,其行文目的是希望读者能够明白:在使用  关于“多层结构”开发模式,存在这样一种争议:一部分学者认为“多层结构”与“面向对象的程序设计思想”有着非常紧密的联系。而另外一部分学者却认为二者之间并无直接联系。写作这篇文章并不是要终结这种争议,其行文目的是希望读者能够明白:在使用asp.net进行Web应用程序开发时,实现“多层结构”开发模式的方法、原理及用意。要顺利的阅读这篇文章,希望读者能对“面向对象的程序设计思想”有一定深度的认识,最好能懂一些“设计模式”的知识。如果你并不了解前面这些,那么这篇文章可能并不适合你现在阅读。不过,无论这篇文章面对的读者是谁,我都会尽量将文章写好。我希望这篇文章能成为学习“三层结构”设计思想的经典文章!


“三层结构”是什么?   关于“多层结构”开发模式,存在这样一种争议:一部分学者认为“多层结构”与“面向对象的程序设计思想”有着非常紧密的联系。而另外一部分学者却认为二者之间并无直接联系。写作这篇文章并不是要终结这种争议,其行文目的是希望读者能够明白:在使用



n 表 现 层:位于最外层(最上层),离用户最近。用于显示数据和接收用户输入的数据,为用户提供一种交互式操作的界面。


n 中间业务层:负责处理用户输入的信息,或者是将这些信息发送给数据访问层进行保存,或者是调用数据访问层中的函数再次读出这些数据。中间业务层也可以包括一些对“商业逻辑”描述代码在里面。


N xml
n 数据访问层:仅实现对数据的保存和读取操作。数据访问,可以访问数据库系统、二进制文件、文本文档或是XML文档。



为什么需要 “三层结构”?——通常的设计方式


在一个大型的 Web应用程序中,如果不分以层次,那么在将来的升级维护中会遇到很大的麻烦。但在这篇文章里我只想以一个简单的留言板程序为示例,说明通常设计方式的不足——



Listlword aspx listlword aspx cs
ListLWord.aspx (后台程序文件ListLWord.aspx.cs)列表显示数据库中的每条留言。


Postlword aspx postlword aspx cs
PostLWord.aspx (后台程序文件PostLWord.aspx.cs)发送留言到数据库。


Codepackage tracelword1
更完整的示例代码,可以到 CodePackage/TraceLWord1目录中找到。数据库中,仅含有一张数据表,其结构如下:


字段名称 数据类型 默认值 备注说明


Lwordid int not null identity 1 1
[LWordID] INT NOT NULLIDENTITY(1, 1) 留言记录编号


Textcontent ntext n
[TextContent] NText N’’ 留言内容


Posttime datetime getdate
[PostTime] DateTime GetDate() 留言发送时间,默认值为当前时间


Listlword aspx
ListLWord.aspx 页面文件(列表显示留言)



Inherits tracelword1 listlword
Inherits="TraceLWord1.ListLWord" %> AutoEventWireup="false"


002 doctype html public w3c dtd html 4 0 transitional en
#002 AutoEventWireup="false" <!DOCTYPEHTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">


#003 AutoEventWireup="false"


004 html
#004 AutoEventWireup="false" <html>


005 head
#005 AutoEventWireup="false" <head>


006 title listlword title
#006 AutoEventWireup="false" <title>ListLWord</title>


007 meta name generator content microsoft visual studio net 7 1
#007 AutoEventWireup="false" <metaname="GENERATOR"Content="Microsoft Visual Studio .NET 7.1">


008 meta name code language content c
#008 AutoEventWireup="false" <metaname="CODE_LANGUAGE"Content="C#">


009 meta name vs defaultclientscript content javascript
#009 AutoEventWireup="false" <metaname=vs_defaultClientScriptcontent="JavaScript">


010 meta name vs targetschema content http schemas microsoft com intellisense ie5
#010 AutoEventWireup="false" <metaname=vs_targetSchemacontent="http://schemas.microsoft.com/intellisense/ie5">


011 head
#011 AutoEventWireup="false" </head>


012 body ms positioning gridlayout
#012 AutoEventWireup="false" <bodyMS_POSITIONING="GridLayout">


#013 AutoEventWireup="false"


014 form id aspnetform method post runat server
#014 AutoEventWireup="false" <formid="__aspNetForm"method="post"runat="server">


#015 AutoEventWireup="false"


016 a href postlword aspx a
#016 AutoEventWireup="false" <ahref="PostLWord.aspx">发送新留言</a>


#017 AutoEventWireup="false"


018 asp datalist id m lwordlistctrl runat server
#018 AutoEventWireup="false" <asp:DataListID="m_lwordListCtrl"Runat="Server">


019 itemtemplate
#019 AutoEventWireup="false" <ItemTemplate>


020 div
#020 AutoEventWireup="false" <div>


021 databinder eval container dataitem posttime
#021 AutoEventWireup="false" <%# DataBinder.Eval(Container.DataItem, "PostTime") %>


022 databinder eval container dataitem textcontent
#022 AutoEventWireup="false" <%# DataBinder.Eval(Container.DataItem, "TextContent") %>


023 div
#023 AutoEventWireup="false" </div>


024 itemtemplate
#024 AutoEventWireup="false" </ItemTemplate>


025 asp datalist
#025 AutoEventWireup="false" </asp:DataList>


#026 AutoEventWireup="false"


027 form
#027 AutoEventWireup="false" </form>


#028 AutoEventWireup="false"


029 body
#029 AutoEventWireup="false" </body>


030 html
#030 AutoEventWireup="false" </html>



Visual studio net 2003 listlword aspx listlword aspx cs
这些代码可以在 Visual Studio.NET 2003开发环境的设计视图中快速建立。ListLWord.aspx 后台程序文件ListLWord.aspx.cs


001 using system
#001 usingSystem;


002 using system collections
#002 usingSystem.Collections;


003 using system componentmodel
#003 usingSystem.ComponentModel;


004 using system data
#004 usingSystem.Data;


005 using system data oledb access
#005 usingSystem.Data.OleDb;// 需要操作Access 数据库


006 using system drawing
#006 usingSystem.Drawing;


007 using system web
#007 usingSystem.Web;


008 using system web sessionstate
#008 usingSystem.Web.SessionState;


009 using system web ui
#009 usingSystem.Web.UI;


010 using system web ui webcontrols
#010 usingSystem.Web.UI.WebControls;


011 using system web ui htmlcontrols
#011 usingSystem.Web.UI.HtmlControls;



013 namespace tracelword1
#013 namespaceTraceLWord1



015 summary
#015 ///<summary>


016 listlword
#016 ///ListLWord 列表留言板信息


017 summary
#017 ///</summary>


018 public class listlword system web ui page
#018 publicclassListLWord : System.Web.UI.Page



#020 // 留言列表控件


021 protected system web ui webcontrols datalist m lwordlistctrl
#021 protectedSystem.Web.UI.WebControls.DataList m_lwordListCtrl;



023 summary
#023 ///<summary>


024 listlword aspx
#024 ///ListLWord.aspx 页面加载函数


025 summary
#025 ///</summary>


026 private void page load object sender system eventargs e
#026 privatevoidPage_Load(objectsender, System.EventArgs e)



028 lword databind
#028 LWord_DataBind();




031 region web
#031 #regionWeb 窗体设计器生成的代码


032 override protected void oninit eventargs e
#032 overrideprotectedvoidOnInit(EventArgs e)



034 initializecomponent
#034 InitializeComponent();


035 base oninit e
#035 base.OnInit(e);




038 private void initializecomponent
#038 privatevoidInitializeComponent()



040 this load new system eventhandler this page load
#040 this.Load+=newSystem.EventHandler(this.Page_Load);



042 endregion
#042 #endregion



044 summary
#044 ///<summary>


#045 ///绑定留言信息列表


046 summary
#046 ///</summary>


047 private void lword databind
#047 privatevoidLWord_DataBind()



049 string mdbconn @ provider microsoft jet oledb 4 0
#049 [email protected]"PROVIDER=Microsoft.Jet.OLEDB.4.0;



050 string cmdtext @ select from lword order by lwordid desc
#050 [email protected]"SELECT * FROM [LWord] ORDER BY [LWordID] DESC";



052 oledbconnection dbconn new oledbconnection mdbconn
#052 OleDbConnectiondbConn=newOleDbConnection(mdbConn);


053 oledbdataadapter dbadp new oledbdataadapter cmdtext dbconn
#053 OleDbDataAdapterdbAdp=newOleDbDataAdapter(cmdText, dbConn);



055 dataset ds new dataset
#055 DataSet ds=newDataSet();


056 dbadp fill ds @ lwordtable
#056 dbAdp.Fill(ds, @"LWordTable");



058 m lwordlistctrl datasource ds tables @ lwordtable defaultview
#058 m_lwordListCtrl.DataSource=ds.Tables[@"LWordTable"].DefaultView;


059 m lwordlistctrl databind
#059 m_lwordListCtrl.DataBind();





Postlword aspx
PostLWord.aspx 页面文件(发送留言到数据库)



Inherits tracelword1 postlword
Inherits="TraceLWord1.PostLWord" %> AutoEventWireup="false"


002 doctype html public w3c dtd html 4 0 transitional en1
#002 AutoEventWireup="false" <!DOCTYPEHTML PUBLIC"-//W3C//DTD HTML 4.0 Transitional//EN">


#003 AutoEventWireup="false"


004 html1
#004 AutoEventWireup="false" <html>


005 head1
#005 AutoEventWireup="false" <head>


006 title postlword title
#006 AutoEventWireup="false" <title>PostLWord</title>


007 meta name generator content microsoft visual studio net 7 11
#007 AutoEventWireup="false" <metaname="GENERATOR"Content="Microsoft Visual Studio .NET 7.1">


008 meta name code language content c1
#008 AutoEventWireup="false" <metaname="CODE_LANGUAGE"Content="C#">


009 meta name vs defaultclientscript content javascript1
#009 AutoEventWireup="false" <metaname=vs_defaultClientScriptcontent="JavaScript">


010 meta name vs targetschema content http schemas microsoft com intellisense ie51
#010 AutoEventWireup="false" <metaname=vs_targetSchemacontent="http://schemas.microsoft.com/intellisense/ie5">


011 head1
#011 AutoEventWireup="false" </head>


012 body ms positioning gridlayout1
#012 AutoEventWireup="false" <bodyMS_POSITIONING="GridLayout">


#013 AutoEventWireup="false"


014 form id aspnetform method post runat server1
#014 AutoEventWireup="false" <formid="__aspNetForm"method="post"runat="server">


#015 AutoEventWireup="false"


016 textarea id m txtcontent runat server rows 8 cols 48 textarea
#016 AutoEventWireup="false" <textareaid="m_txtContent"runat="Server"rows=8cols=48></textarea>


017 input type button id m btnpost runat server value
#017 AutoEventWireup="false" <inputtype="Button"id="m_btnPost"runat="Server"value="发送留言"/>


#018 AutoEventWireup="false"


019 form
#019 AutoEventWireup="false" </form>


#020 AutoEventWireup="false"


021 body
#021 AutoEventWireup="false" </body>


022 html
#022 AutoEventWireup="false" </html>


Postlword aspx postlword aspx cs1
PostLWord.aspx AutoEventWireup="false" 后台程序文件PostLWord.aspx.cs


001 using system1
#001 AutoEventWireup="false" usingSystem;


002 using system collections1
#002 AutoEventWireup="false" usingSystem.Collections;


003 using system componentmodel1
#003 AutoEventWireup="false" usingSystem.ComponentModel;


004 using system data1
#004 AutoEventWireup="false" usingSystem.Data;


005 using system data oledb access1
#005 AutoEventWireup="false" usingSystem.Data.OleDb;// 需要操作Access 数据库


006 using system drawing1
#006 AutoEventWireup="false" usingSystem.Drawing;


007 using system web1
#007 AutoEventWireup="false" usingSystem.Web;


008 using system web sessionstate1
#008 AutoEventWireup="false" usingSystem.Web.SessionState;


009 using system web ui1
#009 AutoEventWireup="false" usingSystem.Web.UI;


010 using system web ui webcontrols1
#010 AutoEventWireup="false" usingSystem.Web.UI.WebControls;


011 using system web ui htmlcontrols1
#011 AutoEventWireup="false" usingSystem.Web.UI.HtmlControls;


#012 AutoEventWireup="false"


013 namespace tracelword11
#013 AutoEventWireup="false" namespaceTraceLWord1


#014 { AutoEventWireup="false"


015 summary1
#015 AutoEventWireup="false" ///<summary>


016 postlword
#016 AutoEventWireup="false" ///PostLWord 发送留言到数据库


017 summary1
#017 AutoEventWireup="false" ///</summary>


018 public class postlword system web ui page
#018 AutoEventWireup="false" publicclassPostLWord : System.Web.UI.Page


#019 AutoEventWireup="false" {


#020 AutoEventWireup="false" // 留言内容编辑框


021 protected system web ui htmlcontrols htmltextarea m txtcontent
#021 AutoEventWireup="false" protectedSystem.Web.UI.HtmlControls.HtmlTextArea m_txtContent;


#022 AutoEventWireup="false" // 提交按钮


023 protected system web ui htmlcontrols htmlinputbutton m btnpost
#023 AutoEventWireup="false" protectedSystem.Web.UI.HtmlControls.HtmlInputButton m_btnPost;


#024 AutoEventWireup="false"


025 summary1
#025 AutoEventWireup="false" ///<summary>


026 postlword aspx
#026 AutoEventWireup="false" ///PostLWord.aspx 页面加载函数


027 summary
#027 AutoEventWireup="false" ///</summary>


028 private void page load object sender system eventargs e
#028 AutoEventWireup="false" privatevoidPage_Load(objectsender, System.EventArgs e)


#029 AutoEventWireup="false" {


#030 AutoEventWireup="false" }


#031 AutoEventWireup="false"


032 region web
#032 AutoEventWireup="false" #regionWeb 窗体设计器生成的代码


033 override protected void oninit eventargs e
#033 AutoEventWireup="false" overrideprotectedvoidOnInit(EventArgs e)


#034 AutoEventWireup="false" {


035 initializecomponent
#035 AutoEventWireup="false" InitializeComponent();


036 base oninit e
#036 AutoEventWireup="false" base.OnInit(e);


#037 AutoEventWireup="false" }


#038 AutoEventWireup="false"


039 private void initializecomponent
#039 AutoEventWireup="false" privatevoidInitializeComponent()


#040 AutoEventWireup="false" {


041 this load new system eventhandler this page load
#041 AutoEventWireup="false" this.Load+=newSystem.EventHandler(this.Page_Load);


042 this m btnpost serverclick new eventhandler post serverclick
#042 AutoEventWireup="false" this.m_btnPost.ServerClick+=newEventHandler(Post_ServerClick);


#043 AutoEventWireup="false" }


044 endregion
#044 AutoEventWireup="false" #endregion


046 summary1
#046 AutoEventWireup="false" ///<summary>


#047 AutoEventWireup="false" ///发送留言信息到数据库


048 summary
#048 AutoEventWireup="false" ///</summary>


049 private void post serverclick object sender eventargs e
#049 AutoEventWireup="false" privatevoidPost_ServerClick(objectsender, EventArgs e)


#050 AutoEventWireup="false" {


#051 AutoEventWireup="false" // 获取留言内容


052 string textcontent this m txtcontent value
#052 AutoEventWireup="false" stringtextContent=this.m_txtContent.Value;


#053 AutoEventWireup="false"


#054 AutoEventWireup="false" // 留言内容不能为空


055 if textcontent
#055 AutoEventWireup="false" if(textContent=="")


056 throw new exception
#056 AutoEventWireup="false" thrownewException("留言内容为空");


#057 AutoEventWireup="false"


058 string mdbconn @ provider microsoft jet oledb 4 0 data source c dbfs tracelworddb mdb
#058 AutoEventWireup="false" [email protected]"PROVIDER=Microsoft.Jet.OLEDB.4.0; DATA Source=C:\DbFs\TraceLWordDb.mdb";


059 string cmdtext insert into lword textcontent values @textcontent
#059 AutoEventWireup="false" stringcmdText="INSERT INTO [LWord]([TextContent]) VALUES(@TextContent)";


#060 AutoEventWireup="false"


061 oledbconnection dbconn new oledbconnection mdbconn
#061 AutoEventWireup="false" OleDbConnectiondbConn=newOleDbConnection(mdbConn);


062 oledbcommand dbcmd new oledbcommand cmdtext dbconn
#062 AutoEventWireup="false" OleDbCommanddbCmd=newOleDbCommand(cmdText, dbConn);


#063 AutoEventWireup="false"


#064 AutoEventWireup="false" // 设置留言内容


065 dbcmd parameters add new oledbparameter @textcontent
#065 AutoEventWireup="false" dbCmd.Parameters.Add(newOleDbParameter("@TextContent",


Oledbtype longvarwchar
OleDbType.LongVarWChar)); AutoEventWireup="false"


066 dbcmd parameters @textcontent value textcontent
#066 AutoEventWireup="false" dbCmd.Parameters["@TextContent"].Value=textContent;


#067 AutoEventWireup="false"


068 try
#068 AutoEventWireup="false" try


#069 AutoEventWireup="false" {


070 dbconn open
#070 AutoEventWireup="false" dbConn.Open();


071 dbcmd executenonquery
#071 AutoEventWireup="false" dbCmd.ExecuteNonQuery();


#072 AutoEventWireup="false" }


073 catch
#073 AutoEventWireup="false" catch


#074 AutoEventWireup="false" {


075 throw
#075 AutoEventWireup="false" throw;


#076 AutoEventWireup="false" }


077 finally
#077 AutoEventWireup="false" finally


#078 AutoEventWireup="false" {


079 dbconn close
#079 AutoEventWireup="false" dbConn.Close();


#080 AutoEventWireup="false" }


#081 AutoEventWireup="false"


#082 AutoEventWireup="false" // 跳转到留言显示页面


083 response redirect listlword aspx true
#083 AutoEventWireup="false" Response.Redirect("ListLWord.aspx", true);


#084 AutoEventWireup="false" }


#085 AutoEventWireup="false" }


#086 } AutoEventWireup="false"


Access
仅仅通过两个页面,就完成了一个基于 AutoEventWireup="false" Access数据库的留言功能。



为什么需要“三层结构”? ——数据库升迁、应用程序变化所带来的问题


留言板正式投入使用!但没过多久,我准备把这个留言板程序的数据库升迁到留言板正式投入使用!但没过多久,我准备把这个留言板程序的数据库升迁到Microsoft SQL Server 2000服务器上去!除了要把数据导入到SQL Server 2000中,还得修改相应的.aspx.cs程序文件。也就是说需要把调用OleDbConnection的地方修改成SqlConnection,还要把调用OleDbAdapter的地方,修改成SqlAdapter。虽然这并不是一件很困难的事情,因为整个站点非常小,仅仅只有两个程序文件,所以修改起来并不费劲。但是,如果对于一个大型的商业网站,访问数据库的页面有很多很多,如果以此方法一个页面一个页面地进行修改,那么费时又费力!只是修改了一下数据库,却可能要修改上千张网页。一动百动,这也许就是程序的一种不灵活性……


再假如,我想给留言板加一个限制: 留言板正式投入使用!但没过多久,我准备把这个留言板程序的数据库升迁到

  • n每天上午09时之后到11时之前可以留言,下午则是13时之后到17时之前可以留言

  • n如果当天留言个数小于40,则可以继续留言


那么就需要把相应的代码,添加到留言板正式投入使用!但没过多久,我准备把这个留言板程序的数据库升迁到PostLWord.aspx.cs程序文件中。但是过了一段时间,我又希望去除这个限制,那么还要修改PostLWord.aspx.cs文件。但是,对于一个大型的商业网站,类似于这样的限制,或者称为“商业规则”,复杂又繁琐。而且这些规则很容易随着商家的意志为转移。如果这些规则限制被分散到各个页面中,那么规则一旦变化,就要修改很多的页面!只是修改了一下规则限制,却又可能要修改上千张网页。一动百动,这也许又是程序的一种不灵活性……


Windows web
  最后,留言板使用过一段时间之后,出于某种目的,我希望把它修改成可以在本地运行的  最后,留言板使用过一段时间之后,出于某种目的,我希望把它修改成可以在本地运行的Windows程序,而放弃原来的Web型式。那么对于这个留言板,可以说是“灭顶之灾”。所有代码都要重新写……当然这个例子比较极端,在现实中,这样的情况还是很少会发生的——


为什么需要“三层结构”?  最后,留言板使用过一段时间之后,出于某种目的,我希望把它修改成可以在本地运行的——初探,就从数据库的升迁开始


一个站点中,访问数据库的程序代码散落在各个页面中,就像夜空中的星星一样繁多。这样一动百动的维护,难度可想而知。最难以忍受的是,对这种维护工作的投入,是没有任何价值的一个站点中,访问数据库的程序代码散落在各个页面中,就像夜空中的星星一样繁多。这样一动百动的维护,难度可想而知。最难以忍受的是,对这种维护工作的投入,是没有任何价值的……


有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“门面模式”的应用。如果把一个网站比喻成一家大饭店,那么“门面模式”中的“门面”,就像是饭店的服务生,而一个网站的浏览者,就像是一个来宾。来宾只需要发送命令给服务生,然后服务生就会按照命令办事。至于服务生经历了多少辛苦才把事情办成?那个并不是来宾感兴趣的事情,来宾们只要求服务生尽快把自己交待事情办完。我们就把ListLWord.aspx.cs程序就看成是一个来宾发出的命令,而把新加入的LWordTask.cs程序看成是一个饭店服务生,那么来宾发出的命令就是:


Dataset
“给我读出留言板数据库中的数据,填充到有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“DataSet数据集中并显示出来!”


Postlword aspx cs
而服务生接到命令后,就会依照执行。而有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“PostLWord.aspx.cs程序,让服务生做的是:


“把我的留言内容写入到数据库中!” 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


Tracelword2 codepackage tracelword2
而服务生接到命令后,就会依照执行。这就是有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“TraceLWord2!可以在CodePackage/TraceLWord2目录中找到——


Lwordtask cs lwordtask cs
把所有的有关数据访问的代码都放到有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“LWordTask.cs文件里,LWordTask.cs程序文件如下:


001 using system2
#001 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“usingSystem;


002 using system data
#002 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“usingSystem.Data;


003 using system data oledb access
#003 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“usingSystem.Data.OleDb;// 需要操作Access 数据库


004 using system web
#004 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“usingSystem.Web;


#005 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


006 namespace tracelword2
#006 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“namespaceTraceLWord2


#007 {有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


008 summary
#008 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“///<summary>


009 lwordtask
#009 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“///LWordTask 数据库任务类


010 summary
#010 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“///</summary>


011 public class lwordtask
#011 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“publicclassLWordTask


#012 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“{


#013 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“// 数据库连接字符串


014 private const string db conn @ provider microsoft jet oledb 4 0
#014 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“[email protected]"PROVIDER=Microsoft.Jet.OLEDB.4.0;


Data source c dbfs tracelworddb mdb1
DATA Source=C:\DbFs\TraceLWordDb.mdb"; 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


#015 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


016 summary
#016有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“///<summary>


017 lword dataset
#017 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“///读取数据库表LWord,并填充DataSet 数据集


018 summary
#018 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“///</summary>


019 param name ds param
#019 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“///<param name="ds">填充目标数据集</param>


020 param name tablename param
#020 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“///<param name="tableName">表名称</param>


021 returns returns
#021 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“///<returns>记录行数</returns>


022 public int listlword dataset ds string tablename
#022 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“publicintListLWord(DataSet ds, stringtableName)


#023 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“{


024 string cmdtext select from lword order by lwordid desc
#024 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“stringcmdText="SELECT * FROM [LWord] ORDER BY [LWordID] DESC";


#025 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


026 oledbconnection dbconn new oledbconnection db conn
#026 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“OleDbConnectiondbConn=newOleDbConnection(DB_CONN);


027 oledbdataadapter dbadp new oledbdataadapter cmdtext dbconn
#027 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“OleDbDataAdapterdbAdp=newOleDbDataAdapter(cmdText, dbConn);


#028 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


029 int count dbadp fill ds tablename
#029 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“intcount=dbAdp.Fill(ds, tableName);


#030 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


031 return count
#031 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“returncount;


#032 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“}


#033 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


034 summary
#034 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“///<summary>


#035 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“///发送留言信息到数据库


036 summary
#036 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“///</summary>


037 param name textcontent param
#037 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“///<param name="textContent">留言内容</param>


038 public void postlword string textcontent
#038 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“publicvoidPostLWord(stringtextContent)


#039 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“{


#040 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“// 留言内容不能为空


041 if textcontent null textcontent
#041 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“if(textContent==null|| textContent=="")


042 throw new exception
#042 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“thrownewException("留言内容为空");


#043 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


044 string cmdtext insert into lword textcontent values @textcontent
#044 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“stringcmdText="INSERT INTO [LWord]([TextContent]) VALUES(@TextContent)";


#045 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


046 oledbconnection dbconn new oledbconnection db conn
#046 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“OleDbConnectiondbConn=newOleDbConnection(DB_CONN);


047 oledbcommand dbcmd new oledbcommand cmdtext dbconn
#047 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“OleDbCommanddbCmd=newOleDbCommand(cmdText, dbConn);


#048 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


#049 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“// 设置留言内容


050 dbcmd parameters add new oledbparameter @textcontent oledbtype longvarwchar
#050 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“dbCmd.Parameters.Add(newOleDbParameter("@TextContent", OleDbType.LongVarWChar));


051 dbcmd parameters @textcontent value textcontent
#051 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“dbCmd.Parameters["@TextContent"].Value=textContent;


#052 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


053 try
#053 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“try


#054 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“{


055 dbconn open
#055 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“dbConn.Open();


056 dbcmd executenonquery
#056 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“dbCmd.ExecuteNonQuery();


#057 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“}


058 catch
#058 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“catch


#059 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“{


060 throw
#060 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“throw;


#061 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“}


062 finally
#062 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“finally


#063 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“{


064 dbconn close
#064 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“dbConn.Close();


#065 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“}


#066 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“}


#067 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“}


#068 }有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


如果将数据库从有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“Access 2000修改为SQL Server 2000,那么只需要修改LWordTask.cs这一个文件。如果LWordTask.cs文件太大,也可以把它切割成几个文件或“类”。如果被切割成的“类”还是很多,也可以把这些访问数据库的类放到一个新建的“项目”里。当然,原来的ListLWord.aspx.cs文件应该作以修改,LWord_DataBind函数被修改成:


... 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


046 private void lword databind
#046 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“privatevoidLWord_DataBind()


#047 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“{


048 dataset ds new dataset
#048 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“DataSet ds=newDataSet();


049 new lwordtask listlword ds @ lwordtable
#049 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“(newLWordTask()).ListLWord(ds, @"LWordTable");


#050 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


051 m lwordlistctrl datasource ds tables @ lwordtable defaultview
#051 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“m_lwordListCtrl.DataSource=ds.Tables[@"LWordTable"].DefaultView;


052 m lwordlistctrl databind
#052 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“m_lwordListCtrl.DataBind();


#053 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“}


... 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


Postlword aspx cs post serverclick
原来的有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“PostLWord.aspx.cs文件也应作以修改,Post_ServerClick函数被修改成:


... 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


048 private void post serverclick object sender eventargs e
#048 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“privatevoidPost_ServerClick(objectsender, EventArgs e)


#049 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“{


#050 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“// 获取留言内容


051 string textcontent this m txtcontent value
#051 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“stringtextContent=this.m_txtContent.Value;


#052 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


053 new lwordtask postlword textcontent
#053 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“(newLWordTask()).PostLWord(textContent);


#054 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


#055 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“// 跳转到留言显示页面


056 response redirect listlword aspx true
#056 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“Response.Redirect("ListLWord.aspx", true);


#057 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“}


... 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


  从前面的程序段中可以看出,有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“ListLWord.aspx.cs和PostLWord.aspx.cs这两个文件已经找不到和数据库相关的代码了。只看到一些和LWordTask类有关系的代码,这就符合了“设计模式”中的一种重要原则:“迪米特法则”。“迪米特法则”主要是说:让一个“类”与尽量少的其它的类发生关系。在TraceLWord1中,ListLWord.aspx.cs这个类和OleDbConnection及OleDbDataAdapter都发生了关系,所以它破坏了“迪米特法则”。利用一个“中间人”是“迪米特法则”解决问题的办法,这也是“门面模式”必须遵循的原则。下面就引出这个LWordTask门面类的示意图:


ListLWord.aspx.cs有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“和PostLWord.aspx.cs两个文件对数据库的访问,全部委托LWordTask类这个“中间人”来办理。利用“门面模式”,将页面类和数据库类进行隔离。这样就作到了页面类不依赖于数据库的效果。以一段比较简单的代码来描述这三个程序的关系:


Public class listlword
public class有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“ListLWord


{有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


Private void lword databind
private void有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“LWord_DataBind()


{有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


New lwordtask listlword
(有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“newLWordTask()).ListLWord( ... );


}有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


}有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


Public class postlword
public class有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“PostLWord


{有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


Private void post serverclick object sender eventargs e
private void有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“Post_ServerClick(objectsender, EventArgs e)


{有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


New lwordtask postlword
(有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“newLWordTask()).PostLWord( ... );


}有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


}有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


Public class lwordtask
public class有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“LWordTask


{有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


Public dataset listlword dataset ds
public有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“DataSet ListLWord(DataSet ds)...


Public void postlword string textcontent
public void有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“PostLWord(stringtextContent)...


}有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


应用中间业务层,实现“三层结构” 有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“


前面这种分离数据访问代码的形式,可以说是一种“三层结构”的简化形式。因为它没有“中间业务层”也可以称呼它为“前面这种分离数据访问代码的形式,可以说是一种“三层结构”的简化形式。因为它没有“中间业务层”也可以称呼它为“二层结构”。一个真正的“三层”程序,是要有“中间业务层”的,而它的作用是连接“外观层”和“数据访问层”。换句话说:“外观层”的任务先委托给“中间业务层”来办理,然后“中间业务层”再去委托“数据访问层”来办理……


那么为什么要应用“中间业务层”呢?“中间业务层”的用途有很多,例如:验证用户输入数据、缓存从数据库中读取的数据等等那么为什么要应用“中间业务层”呢?“中间业务层”的用途有很多,例如:验证用户输入数据、缓存从数据库中读取的数据等等……但是,“中间业务层”的实际目的是将“数据访问层”的最基础的存储逻辑组合起来,形成一种业务规则。例如:“在一个购物网站中有这样的一个规则:在该网站第一次购物的用户,系统为其自动注册”。这样的业务逻辑放在中间层最合适:



  在新 TraceLWord3中,应用了“企业级模板项目”。把原来的LWordTask.cs,并放置到一个单一的项目里,项目名称为:AccessTask。解决方案中又新建了一个名称为:InterService的项目,该项目中包含一个LWordService.cs程序文件,它便是“中间业务层”程序。为了不重复命名,TraceLWord3的网站被放置到了WebUI项目中。更完整的代码,可以在CodePackage/TraceLWord3目录中找到——



Lwordservice cs
LWordService.cs 程序源码:


001 using system3
#001 usingSystem;


002 using system data1
#002 usingSystem.Data;



004 using tracelword3 accesstask
#004 usingTraceLWord3.AccessTask;// 引用数据访问层



006 namespace tracelword3 interservice
#006 namespaceTraceLWord3.InterService



008 summary1
#008 ///<summary>


009 lwordservice
#009 ///LWordService 留言板服务类


010 summary1
#010 ///</summary>


011 public class lwordservice
#011 publicclassLWordService



013 summary
#013 ///<summary>


014 lword dataset
#014 ///读取数据库表LWord,并填充DataSet 数据集


015 summary2
#015 ///</summary>


016 param name ds param
#016 ///<param name="ds">填充目标数据集</param>


017 param name tablename param
#017 ///<param name="tableName">表名称</param>


018 returns returns
#018 ///<returns>记录行数</returns>


019 public int listlword dataset ds string tablename
#019 publicintListLWord(DataSet ds, stringtableName)



021 return new lwordtask listlword ds tablename
#021 return(newLWordTask()).ListLWord(ds, tableName);




024 summary
#024 ///<summary>


#025 ///发送留言信息到数据库


026 summary
#026 ///</summary>


027 param name textcontent param
#027 ///<param name="textContent">留言内容</param>


028 public void postlword string content
#028 publicvoidPostLWord(stringcontent)



030 new lwordtask postlword content
#030 (newLWordTask()).PostLWord(content);





LWordService.cs程序文件的行#021和行#030可以看出,“中间业务层”并没有实现什么业务逻辑,只是简单的调用了“数据访问层”的类方法……这样做是为了让读者更直观的看明白“三层结构”应用程序的调用顺序,看清楚它的全貌。加入了“中间业务层”,那么原来的ListLWord.aspx.cs文件应该作以修改:



012 using tracelword3 interservice
#012 usingTraceLWord3.InterService;//引用中间服务层



045 summary
#045 ///<summary>


#046 ///绑定留言信息列表


047 summary
#047 ///</summary>


048 private void lword databind
#048 privatevoidLWord_DataBind()



050 dataset ds new dataset
#050 DataSet ds=newDataSet();


051 new lwordservice listlword ds @ lwordtable
#051 (newLWordService()).ListLWord(ds, @"LWordTable");



053 m lwordlistctrl datasource ds tables @ lwordtable defaultview
#053 m_lwordListCtrl.DataSource=ds.Tables[@"LWordTable"].DefaultView;


054 m lwordlistctrl databind
#054 m_lwordListCtrl.DataBind();




Postlword aspx cs1
原来的 PostLWord.aspx.cs文件也应作以修改:



012 using tracelword3 interservice1
#012 usingTraceLWord3.InterService;// 引用中间服务层



047 summary1
#047 ///<summary>


#048 ///发送留言到数据库


049 summary
#049 ///</summary>


050 private void post serverclick object sender eventargs e
#050 privatevoidPost_ServerClick(objectsender, EventArgs e)



#052 // 获取留言内容


053 string textcontent this m txtcontent value
#053 stringtextContent=this.m_txtContent.Value;



055 new lwordservice postlword textcontent
#055 (newLWordService()).PostLWord(textContent);



#057 // 跳转到留言显示页面


058 response redirect listlword aspx true
#058 Response.Redirect("ListLWord.aspx", true);




Tracelword3
到目前为止, TraceLWord3程序已经是一个简单的“三层结构”的应用程序,以一段比较简单的代码来描述四个程序的关系:


Namespace tracelword3 weblword
namespace TraceLWord3.WebLWord


{


Public class listlword1
public class ListLWord


{


Private void lword databind1
private void LWord_DataBind()


{


New lwordservice listlword
( newLWordService()).ListLWord( ... );


}


}


Public class postlword1
public class PostLWord


{


Private void post serverclick object sender eventargs e1
private void Post_ServerClick(objectsender, EventArgs e)


{


New lwordservice postlword
( newLWordService()).PostLWord( ... );


}


}


}


Namespace tracelword3 interservice
namespace TraceLWord3.InterService


{


Public class lwordtask1
public class LWordTask


{


Public dataset listlword dataset ds string tablename
public DataSet ListLWord(DataSet ds, stringtableName)


{


Return new lwordtask listlword ds tablename
return (newLWordTask()).ListLWord(ds, tableName);


}


Public void postlword string content
public void PostLWord(stringcontent)


{


New lwordtask postlword content
( newLWordTask()).PostLWord(content);


}


}


}


Namespace tracelword3 accesstask
namespace TraceLWord3.AccessTask


{


Public class lwordtask2
public class LWordTask


{


Public dataset listlword dataset ds1
public DataSet ListLWord(DataSet ds)...


Public void postlword string content1
public void PostLWord(stringcontent)...


}


}


Tracelword3 listlword aspx
用户在访问 TraceLWord3的ListLWord.aspx页面时序图:


当一个用户访问 TraceLWord5的ListLWord.aspx页面的时候,会触发该页面后台程序中的Page_Load函数。而在该函数中调用了LWord_DataBind函数来获取留言板信息。由图中可以看到出,LWord_DataBind在被调用的期间,会建立一个新的LWordService类对象,并调用这个对象的ListLWord函数。在LWordService.ListLWord函数被调用的期间,会建立一个新的LWordTask类对象,并调用这个对象的ListLWord来获取留言板信息的。PostLWord.aspx页面时序图,和上面这个差不多。就是这样,经过一层又一层的调用,来获取返回结果或是保存数据。


注意:从时序图中可以看出,当子程序模块未执行结束时,主程序模块只能处于等待状态。这说明将应用程序划分层次,会带来其执行速度上的一些损失注意:从时序图中可以看出,当子程序模块未执行结束时,主程序模块只能处于等待状态。这说明将应用程序划分层次,会带来其执行速度上的一些损失……


对“三层结构”的深入理解注意:从时序图中可以看出,当子程序模块未执行结束时,主程序模块只能处于等待状态。这说明将应用程序划分层次,会带来其执行速度上的一些损失——怎样才算是一个符合“三层结构”的Web应用程序?


在一个注意:从时序图中可以看出,当子程序模块未执行结束时,主程序模块只能处于等待状态。这说明将应用程序划分层次,会带来其执行速度上的一些损失ASP.NET Web应用程序解决方案中,并不是说有aspx文件、有dll文件、还有数据库,就是“三层结构”的Web应用程序,这样的说法是不对的。也并不是说没有对数据库进行操作,就不是“三层结构”的。其实“三层结构”是功能实现上的三层。例如,在微软的ASP.NET示范实例“Duwamish7”中,“表现层”被放置在“Web”项目中,“中间业务层”是放置在“BusinessFacade”项目中,“数据访问层”则是放置在“DataAccess”项目中……而在微软的另一个ASP.NET示范实例“PetShop3.0”中,“表现层”被放置在“Web”项目中,“中间业务层”是放置在“BLL”项目中,而“数据访问层”则是放置在“SQLServerDAL”和“OracleDAL”两个项目中。在Bincess.CN彬月论坛中,“表现层”是被放置在“WebForum”项目中,“中间业务(服务)层”是被放置在“InterService”项目中,而“数据访问层”是被放置在“SqlServerTask”项目中。


  如果只以分层的设计角度看,注意:从时序图中可以看出,当子程序模块未执行结束时,主程序模块只能处于等待状态。这说明将应用程序划分层次,会带来其执行速度上的一些损失Duwamish7要比PetShop3.0复杂一些!而如果较为全面的比较二者,PetShop3.0则显得比较复杂。但我们先不讨论这些,对PetShop3.0和Duwamish7的研究,并不是本文的重点。现在的问题就是:既然“三层结构”已经被分派到各自的项目中,那么剩下来的项目是做什么的呢?例如PetShop3.0中的“Model”、“IDAL”、“DALFactory”这三个项目,再例如Duwamish7中的“Common”项目,还有就是在Bincess.CN彬月论坛中的“Classes”、“DbTask”、这两个项目。它们究竟是做什么用的呢?


对“三层结构”的深入理解注意:从时序图中可以看出,当子程序模块未执行结束时,主程序模块只能处于等待状态。这说明将应用程序划分层次,会带来其执行速度上的一些损失——从一家小餐馆说起


  一个“三层结构”的注意:从时序图中可以看出,当子程序模块未执行结束时,主程序模块只能处于等待状态。这说明将应用程序划分层次,会带来其执行速度上的一些损失Web应用程序,就好象是一家小餐馆。


N aspx
n注意:从时序图中可以看出,当子程序模块未执行结束时,主程序模块只能处于等待状态。这说明将应用程序划分层次,会带来其执行速度上的一些损失表 现 层,所有的.aspx页面就好像是这家餐馆的菜谱。


n注意:从时序图中可以看出,当子程序模块未执行结束时,主程序模块只能处于等待状态。这说明将应用程序划分层次,会带来其执行速度上的一些损失中间业务层,就像是餐馆的服务生。


n注意:从时序图中可以看出,当子程序模块未执行结束时,主程序模块只能处于等待状态。这说明将应用程序划分层次,会带来其执行速度上的一些损失数据访问层,就像是餐馆的大厨师傅。


n注意:从时序图中可以看出,当子程序模块未执行结束时,主程序模块只能处于等待状态。这说明将应用程序划分层次,会带来其执行速度上的一些损失而我们这些网站浏览者,就是去餐馆吃饭的吃客了……


我们去一家餐馆吃饭,首先得看他们的菜谱,然后唤来服务生,告诉他我们想要吃的菜肴。服务生记下来以后,便会马上去通知大厨师傅要烹制这些菜。大厨师傅收到通知后,马上起火烧菜。过了不久,服务生便把一道一道香喷喷的、热气腾腾的美味端到我们的桌位上我们去一家餐馆吃饭,首先得看他们的菜谱,然后唤来服务生,告诉他我们想要吃的菜肴。服务生记下来以后,便会马上去通知大厨师傅要烹制这些菜。大厨师傅收到通知后,马上起火烧菜。过了不久,服务生便把一道一道香喷喷的、热气腾腾的美味端到我们的桌位上——


而我们访问一个基于我们去一家餐馆吃饭,首先得看他们的菜谱,然后唤来服务生,告诉他我们想要吃的菜肴。服务生记下来以后,便会马上去通知大厨师傅要烹制这些菜。大厨师傅收到通知后,马上起火烧菜。过了不久,服务生便把一道一道香喷喷的、热气腾腾的美味端到我们的桌位上asp.net技术的网站的时候,首先打开的是一个aspx页面。这个aspx页面的后台程序会去调用中间业务层的相应函数来获取结果。中间业务层又会去调用数据访问层的相应函数来获取结果。在一个用户访问TraceLWord3打开ListLWord.aspx页面查看留言的时候,其后台程序ListLWord.aspx.cs会去调用位于中间业务层LWordService的ListLWord(DataSet ds)函数。然后这个函数又会去调用位于数据访问层AccessTask的ListLWord(DataSet ds)函数。最后把结果显示出来……


对比一下示意图: 我们去一家餐馆吃饭,首先得看他们的菜谱,然后唤来服务生,告诉他我们想要吃的菜肴。服务生记下来以后,便会马上去通知大厨师傅要烹制这些菜。大厨师傅收到通知后,马上起火烧菜。过了不久,服务生便把一道一道香喷喷的、热气腾腾的美味端到我们的桌位上


从示意图看,这两个过程是否非常相似呢? 我们去一家餐馆吃饭,首先得看他们的菜谱,然后唤来服务生,告诉他我们想要吃的菜肴。服务生记下来以后,便会马上去通知大厨师傅要烹制这些菜。大厨师傅收到通知后,马上起火烧菜。过了不久,服务生便把一道一道香喷喷的、热气腾腾的美味端到我们的桌位上


Asp net aspx
不同的地方只是在于,去餐馆吃饭,需要吃客自己唤来服务生。而访问一个不同的地方只是在于,去餐馆吃饭,需要吃客自己唤来服务生。而访问一个asp.net网站,菜单可以代替吃客唤来服务生。在最后的返回结果上,把结果返回给aspx页面,也就是等于把结果返回给浏览者了。


高度的“面向对象思想”的体现不同的地方只是在于,去餐馆吃饭,需要吃客自己唤来服务生。而访问一个——封装


在我们去餐馆吃饭的这个过程中,像我这样在餐馆中的吃客,最关心的是什么呢?当然是:餐馆的饭菜是不是好吃,是不是很卫生?价格是不是公道?在我们去餐馆吃饭的这个过程中,像我这样在餐馆中的吃客,最关心的是什么呢?当然是:餐馆的饭菜是不是好吃,是不是很卫生?价格是不是公道?……而餐馆中的服务生会关心什么呢?应该是:要随时注意响应每位顾客的吩咐,要记住顾客在哪个桌位上?还要把顾客点的菜记在本子上……餐馆的大厨师傅会关心什么呢?应该是:一道菜肴的做法是什么?怎么提高烧菜的效率?研究新菜式……大厨师傅,烧好菜肴之后,只管把菜交给服务生就完事了。至于服务生把菜送到哪个桌位上去了?是哪个顾客吃了他做的菜,大厨师傅才不管咧——服务生只要记得把我点的菜肴端来,就成了。至于这菜是怎么烹饪的?顾客干麻要点这道菜?他才不管咧——而我,只要知道这菜味道不错,价格公道,干净卫生,其他的我才不管咧——


这里面不正是高度的体现了“在我们去餐馆吃饭的这个过程中,像我这样在餐馆中的吃客,最关心的是什么呢?当然是:餐馆的饭菜是不是好吃,是不是很卫生?价格是不是公道?面向对象思想”的“封装”原则吗?


无论大厨师傅在什么时候研究出新的菜式,都不会耽误我现在吃饭。就算服务生忘记我的桌位号是多少了,也不可能因此让大厨师傅忘记菜肴的做法?无论大厨师傅在什么时候研究出新的菜式,都不会耽误我现在吃饭。就算服务生忘记我的桌位号是多少了,也不可能因此让大厨师傅忘记菜肴的做法?在我去餐馆吃饭的这个过程中,我、餐馆服务生、大厨师傅,是封装程度极高的三个个体。当其中的一个个体内部发生变化的时候,并不会波及到其他个体。这便是面向对象封装特性的一个益处!


土豆炖牛肉盖饭与实体规范 无论大厨师傅在什么时候研究出新的菜式,都不会耽误我现在吃饭。就算服务生忘记我的桌位号是多少了,也不可能因此让大厨师傅忘记菜肴的做法?


  在我工作过的第一家公司楼下,有一家成都风味的小餐馆,每天中午我都和几个同事一起去那家小餐馆吃饭。公司附近只有这么一家餐馆,不过那里的饭菜还算不错。我最喜欢那里的“土豆炖牛肉盖饭”,也很喜欢那里的“鸡蛋汤”,那种美味至今难忘  在我工作过的第一家公司楼下,有一家成都风味的小餐馆,每天中午我都和几个同事一起去那家小餐馆吃饭。公司附近只有这么一家餐馆,不过那里的饭菜还算不错。我最喜欢那里的“土豆炖牛肉盖饭”,也很喜欢那里的“鸡蛋汤”,那种美味至今难忘……所谓“盖饭”,又称是“盖浇饭”,就是把烹饪好的菜肴直接遮盖在铺在盘子里的米饭上。例如“土豆炖牛肉盖饭”,就是把一锅热气腾腾的“土豆炖牛肉”遮盖在米饭上——







三番几次 ……


我对服务生大怒道:好吃的,好吃的,你难道不明白吗?!我对服务生大怒道:好吃的,好吃的,你难道不明白吗?!——


这样的情况是没有可能发生的!因为我没有明确地说出来我到底要吃什么?所以服务生也没办法为我服务这样的情况是没有可能发生的!因为我没有明确地说出来我到底要吃什么?所以服务生也没办法为我服务……


问题后果:我可能被送往附近医院的精神科这样的情况是没有可能发生的!因为我没有明确地说出来我到底要吃什么?所以服务生也没办法为我服务……


情形二: 这样的情况是没有可能发生的!因为我没有明确地说出来我到底要吃什么?所以服务生也没办法为我服务


我对服务生道:给我一份土豆炖牛肉盖饭! 这样的情况是没有可能发生的!因为我没有明确地说出来我到底要吃什么?所以服务生也没办法为我服务


服务生对大厨师傅道:做一份宫爆鸡丁这样的情况是没有可能发生的!因为我没有明确地说出来我到底要吃什么?所以服务生也没办法为我服务——















这样的情况更是没有可能发生的!必定,现实生活不是这样的情况更是没有可能发生的!必定,现实生活不是《西游记》。必定,这篇文章是学术文章而不是《哈里波特》……


问题后果:这样的情况更是没有可能发生的!必定,现实生活不是……


如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在TraceLWord3这个项目中呢?似乎上面这些荒唐的事情都成真了。(我想,不仅仅是在TraceLWord3这样的项目中,作为这篇文章的读者,你是否也经历过像这一样荒唐的项目而全然未知呢?)


Listlword aspx cs
首先在如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在ListLWord.aspx.cs文件


... 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在


048 private void lword databind1
#048 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在privatevoidLWord_DataBind()


#049 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在{


050 dataset ds new dataset1
#050 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在DataSet ds=newDataSet();


051 new lwordservice listlword ds @ lwordtable1
#051 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在(newLWordService()).ListLWord(ds, @"LWordTable");


#052 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在


053 m lwordlistctrl datasource ds tables @ lwordtable defaultview1
#053 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在m_lwordListCtrl.DataSource=ds.Tables[@"LWordTable"].DefaultView;


054 m lwordlistctrl databind1
#054 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在m_lwordListCtrl.DataBind();


#055 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在}


... 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在


  在如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在ListLWord.aspx.cs文件中,使用的是DataSet对象来取得留言板信息的。但是DataSet是不明确的!为什么这么说呢?行#051由LWordService填充的DataSet中可以集合任意的数据表DataTable,而在这些被收集的DataTable中,不一定会有一个是我们期望得到的。假设,LWordService类中的ListLWord函数其函数内容是:


... 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在


006 namespace tracelword3 interservice1
#006 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在namespaceTraceLWord3.InterService


#007 {如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在


... 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在


011 public class lwordservice1
#011 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在publicclassLWordService


#012 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在{


... 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在


019 public int listlword dataset ds string tablename1
#019 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在publicintListLWord(DataSet ds, stringtableName)


#020 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在{


021 ds tables clear
#021如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在ds.Tables.Clear();


022 ds tables add new datatable tablename
#022如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在ds.Tables.Add(newDataTable(tableName));


#023如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在


024 return 1
#024 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在return1;


#025 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在}


... 如果上面这些荒唐的事情都成了现实,那么我肯定永远都不敢再来这家餐馆吃饭了。这些让我感到极大的不安。而在


Listlword aspx1
函数中清除了数据集中所有的表之后,加入了一个新的数据表后就匆匆返回了。这样作的后果,会直接影响函数中清除了数据集中所有的表之后,加入了一个新的数据表后就匆匆返回了。这样作的后果,会直接影响ListLWord.aspx。


... 函数中清除了数据集中所有的表之后,加入了一个新的数据表后就匆匆返回了。这样作的后果,会直接影响


018 asp datalist id m lwordlistctrl runat server1
#018 函数中清除了数据集中所有的表之后,加入了一个新的数据表后就匆匆返回了。这样作的后果,会直接影响<asp:DataListID="m_lwordListCtrl"Runat="Server">


019 itemtemplate1
#019 函数中清除了数据集中所有的表之后,加入了一个新的数据表后就匆匆返回了。这样作的后果,会直接影响<ItemTemplate>


020 div1
#020 函数中清除了数据集中所有的表之后,加入了一个新的数据表后就匆匆返回了。这样作的后果,会直接影响<div><!--// 会提示找不到下面这两个字段//-->


021 databinder eval container dataitem posttime1
#021 函数中清除了数据集中所有的表之后,加入了一个新的数据表后就匆匆返回了。这样作的后果,会直接影响<%# DataBinder.Eval(Container.DataItem, "PostTime") %>


022 databinder eval container dataitem textcontent1
#022 函数中清除了数据集中所有的表之后,加入了一个新的数据表后就匆匆返回了。这样作的后果,会直接影响<%# DataBinder.Eval(Container.DataItem, "TextContent") %>


023 div1
#023 函数中清除了数据集中所有的表之后,加入了一个新的数据表后就匆匆返回了。这样作的后果,会直接影响</div>


024 itemtemplate1
#024 函数中清除了数据集中所有的表之后,加入了一个新的数据表后就匆匆返回了。这样作的后果,会直接影响</ItemTemplate>


025 asp datalist1
#025 函数中清除了数据集中所有的表之后,加入了一个新的数据表后就匆匆返回了。这样作的后果,会直接影响</asp:DataList>


... 函数中清除了数据集中所有的表之后,加入了一个新的数据表后就匆匆返回了。这样作的后果,会直接影响



Lwordservice cs1
其次,再看 LWordService.cs文件



019 public int listlword dataset ds string tablename2
#019 publicintListLWord(DataSet ds, stringtableName)



021 return new lwordtask listlword ds tablename1
#021 return(newLWordTask()).ListLWord(ds, tableName);




  在 LWordService.cs文件中,也是使用DataSet对象来取得留言板信息的。这个DataSet同样的不明确,含糊不清的指令还在执行……行#021由LWordTask填充的DataSet不一定会含有我们希望得到的表。即便是行#019中的DataSet参数已经明确的定义了每个表的结构,那么在带入行#021之后,可能也会变得混淆。例如,LWordTask类中的ListLWord函数其函数内容是:



006 namespace tracelword21
#006 namespaceTraceLWord2




011 public class lwordtask1
#011 publicclassLWordTask




022 public int listlword dataset ds string tablename1
#022 publicintListLWord(DataSet ds, stringtableName)



024 ds tables clear
#024 ds.Tables.Clear();



026 sql reguser lword
#026 // 在SQL语句里选取了[RegUser] 表而非[LWord] 表


027 string cmdtext select from reguser order by reguserid desc
#027 stringcmdText="SELECT * FROM [RegUser]ORDER BY [RegUserID] DESC";



029 oledbconnection dbconn new oledbconnection db conn
#029 OleDbConnectiondbConn=newOleDbConnection(DB_CONN);


030 oledbdataadapter dbadp new oledbdataadapter cmdtext dbconn
#030 OleDbDataAdapterdbAdp=newOleDbDataAdapter(cmdText, dbConn);



032 int count dbadp fill ds tablename
#032 intcount=dbAdp.Fill(ds, tableName);



034 return count
#034 returncount;




函数中清除了数据集中所有的表之后,选取了注册用户数据表函数中清除了数据集中所有的表之后,选取了注册用户数据表[RegUser]对DataSet进行填充并返回。也就是说,即便是LWordService.cs文件中行#019中的DataSet参数已经明确的定义了每个表的结构,也可能会出现和前面提到的和“情形三”一样结果。


Lwordtask cs
最后,再看看函数中清除了数据集中所有的表之后,选取了注册用户数据表LWordTask.cs文件


... 函数中清除了数据集中所有的表之后,选取了注册用户数据表


022 public int listlword dataset ds string tablename2
#022 函数中清除了数据集中所有的表之后,选取了注册用户数据表publicintListLWord(DataSet ds, stringtableName)


#023 函数中清除了数据集中所有的表之后,选取了注册用户数据表{


024 string cmdtext select from lword order by lwordid desc1
#024 函数中清除了数据集中所有的表之后,选取了注册用户数据表stringcmdText="SELECT * FROM [LWord]ORDER BY [LWordID] DESC";


#025 函数中清除了数据集中所有的表之后,选取了注册用户数据表


026 oledbconnection dbconn new oledbconnection db conn1
#026 函数中清除了数据集中所有的表之后,选取了注册用户数据表OleDbConnectiondbConn=newOleDbConnection(DB_CONN);


027 oledbdataadapter dbadp new oledbdataadapter cmdtext dbconn1
#027 函数中清除了数据集中所有的表之后,选取了注册用户数据表OleDbDataAdapterdbAdp=newOleDbDataAdapter(cmdText, dbConn);


#028 函数中清除了数据集中所有的表之后,选取了注册用户数据表


029 int count dbadp fill ds tablename1
#029 函数中清除了数据集中所有的表之后,选取了注册用户数据表intcount=dbAdp.Fill(ds, tableName);


#030 函数中清除了数据集中所有的表之后,选取了注册用户数据表


031 return count1
#031 函数中清除了数据集中所有的表之后,选取了注册用户数据表returncount;


#032 函数中清除了数据集中所有的表之后,选取了注册用户数据表}


... 函数中清除了数据集中所有的表之后,选取了注册用户数据表



  我们不能只坐在那里期盼着我们的程序会往好的方向发展,这样很被动。写出上面的这些程序段,必须小心翼翼。就连数据库表中的字段命名都要一审再审。一旦变化,就直接影响到位于“表现层”的  我们不能只坐在那里期盼着我们的程序会往好的方向发展,这样很被动。写出上面的这些程序段,必须小心翼翼。就连数据库表中的字段命名都要一审再审。一旦变化,就直接影响到位于“表现层”的ListLWord.aspx文件。仅仅是为了顺利的完成TraceLWord3这个“大型项目”,页面设计师要和程序员还有数据库管理员要进行额外的沟通。我们需要一个“土豆炖牛肉盖饭”式的强制标准!——


引入实体规范   我们不能只坐在那里期盼着我们的程序会往好的方向发展,这样很被动。写出上面的这些程序段,必须小心翼翼。就连数据库表中的字段命名都要一审再审。一旦变化,就直接影响到位于“表现层”的


为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在TraceLWord4中,引入了Classes项目。在这个项目里,只有一个LWord.cs程序文件。这是一个非常重要的文件,它属于“实体规范层”,如果是在一个Java项目中,Classes可以看作是:“实体Bean”。更完整的代码,可以在CodePackage/TraceLWord4目录中找到——


Lword cs
LWord.cs为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在文件内容如下:


001 using system4
#001 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在usingSystem;


#002 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


003 namespace tracelword4 classes
#003 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在namespaceTraceLWord4.Classes


#004 {为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


005 summary
#005 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///<summary>


006 lword
#006 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///LWord 留言板类定义


007 summary
#007 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///</summary>


008 public class lword
#008 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在publicclassLWord


#009 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在{


#010 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在// 编号


011 private int m uniqueid
#011 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在privateintm_uniqueID;


#012 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在// 文本内容


013 private string m textcontent
#013 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在privatestringm_textContent;


#014 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在// 发送时间


015 private datetime m posttime
#015 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在privateDateTime m_postTime;


#016 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


017 region lword
#017 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在#region类LWord 构造器


018 summary1
#018 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///<summary>


019 lword
#019 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///类LWord 默认构造器


020 summary
#020 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///</summary>


021 public lword
#021 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在publicLWord()


#022 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在{


#023 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在}


#024 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


025 summary2
#025 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///<summary>


026 lword
#026 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///类LWord 参数构造器


027 summary1
#027 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///</summary>


028 param name uniqueid param
#028 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///<param name="uniqueID">留言编号</param>


029 public lword int uniqueid
#029 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在publicLWord(intuniqueID)


#030 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在{


031 this uniqueid uniqueid
#031 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在this.UniqueID=uniqueID;


#032 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在}


033 endregion
#033 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在#endregion


#034 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


035 summary
#035 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///<summary>


#036 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///设置或获取留言编号


037 summary
#037 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///</summary>


038 public int uniqueid
#038 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在publicintUniqueID


#039 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在{


040 set
#040 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在set


#041 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在{


042 this m uniqueid value 0 0 value
#042为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在this.m_uniqueID=(value<=0? 0: value);


#043 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在}


#044 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


045 get
#045 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在get


#046 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在{


047 return this m uniqueid
#047 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在returnthis.m_uniqueID;


#048 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在}


#049 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在}


#050 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


051 summary
#051 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///<summary>


#052 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///设置或获取留言内容


053 summary
#053 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///</summary>


054 public string textcontent
#054 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在publicstringTextContent


#055 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在{


056 set
#056 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在set


#057 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在{


058 this m textcontent value
#058 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在this.m_textContent=value;


#059 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在}


#060 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


061 get
#061 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在get


#062 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在{


063 return this m textcontent
#063 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在returnthis.m_textContent;


#064 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在}


#065 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在}


#066 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


067 summary
#067 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///<summary>


#068 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///设置或获取发送时间


069 summary
#069 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///</summary>


070 public datetime posttime
#070 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在publicDateTime PostTime


#071 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在{


072 set
#072 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在set


#073 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在{


074 this m posttime value
#074 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在this.m_postTime=value;


#075 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在}


#076 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


077 get
#077 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在get


#078 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在{


079 return this m posttime
#079 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在returnthis.m_postTime;


#080 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在}


#081 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在}


#082 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在}


#083 }为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


Lwordservice lwordtask lwordservice
这个强制标准,为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在LWordService和LWordTask都必须遵守!所以LWordService相应的要做出变化:


001 using system5
#001为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在usingSystem;


002 using system data2
#002 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在usingSystem.Data;


#003 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


004 using tracelword4 accesstask
#004 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在usingTraceLWord4.AccessTask;// 引用数据访问层


005 using tracelword4 classes
#005 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在usingTraceLWord4.Classes;// 引用实体规范层


#006 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


007 namespace tracelword4 interservice
#007 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在namespaceTraceLWord4.InterService


#008 {为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


009 summary
#009 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///<summary>


010 lwordservice
#010 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///LWordService 留言板服务类


011 summary
#011 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///</summary>


012 public class lwordservice
#012 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在publicclassLWordService


#013 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在{


014 summary
#014 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///<summary>


015 lword
#015 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///读取LWord 数据表,返回留言对象数组


016 summary1
#016 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///</summary>


017 returns returns
#017 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///<returns></returns>


018 public lword listlword
#018 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在publicLWord[] ListLWord()


#019 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在{


020 return new lwordtask listlword
#020 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在return(newLWordTask()).ListLWord();


#021 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在}


#022 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


023 summary1
#023 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///<summary>


#024 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///发送留言信息到数据库


025 summary3
#025 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///</summary>


026 param name newlword param
#026 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///<param name="newLWord">留言对象</param>


027 public void postlword lword newlword
#027 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在publicvoidPostLWord(LWord newLWord)


#028 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在{


029 new lwordtask postlword newlword
#029 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在(newLWordTask()).PostLWord(newLWord);


#030 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在}


#031 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在}


#032 }为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


从行为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在#018中可以看出,无论如何,ListLWord函数都要返回一个LWord数组!这个数组可能为空值,但是一旦数组的长度不为零,那么其中的元素必定是一个LWord类对象!而一个LWord类对象,就一定有TextContent和PostTime这两个属性!这个要比DataSet类对象作为参数的形式明确得多……同样的,LWordTask也要做出反应:


001 using system6
#001 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在usingSystem;


002 using system collections2
#002 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在usingSystem.Collections;


003 using system data
#003 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在usingSystem.Data;


004 using system data oledb
#004 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在usingSystem.Data.OleDb;


005 using system web
#005 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在usingSystem.Web;


#006 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


007 using tracelword4 classes
#007 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在usingTraceLWord4.Classes;// 引用实体规范层


#008 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


009 namespace tracelword4 accesstask
#009 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在namespaceTraceLWord4.AccessTask


#010 {为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


011 summary1
#011 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///<summary>


012 lwordtask
#012 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///LWordTask 留言板任务类


013 summary1
#013 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///</summary>


014 public class lwordtask
#014 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在publicclassLWordTask


#015 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在{


#016 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在// 数据库连接字符串


017 private const string db conn @ provider microsoft jet oledb 4 0
#017 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在[email protected]"PROVIDER=Microsoft.Jet.OLEDB.4.0;


Data source c dbfs tracelworddb mdb2
DATA Source=C:\DbFs\TraceLWordDb.mdb"; 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


#018 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在


019 summary
#019 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///<summary>


020 lword
#020 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///读取LWord 数据表,返回留言对象数组


021 summary
#021 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///</summary>


022 returns returns
#022 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在///<returns></returns>


023 public lword listlword
#023 为了达到一种“土豆炖牛肉盖饭”式的强制标准,所以在publicLWord[] ListLWord()