打印

[asp.net教程] 浅谈“三层结构”原理与用意 4

浅谈“三层结构”原理与用意 4

为什么需要“三层结构”?——数据库升迁、应用程序变化所带来的问题
   
  留言板正式投入使用!但没过多久,我准备把这个留言板程序的数据库升迁到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型式。那么对于这个留言板,可以说是“灭顶之灾”。所有代码都要重新写……当然这个例子比较极端,在现实中,这样的情况还是很少会发生的——
   
   
   
  为什么需要“三层结构”?——初探,就从数据库的升迁开始
   
  一个站点中,访问数据库的程序代码散落在各个页面中,就像夜空中的星星一样繁多。这样一动百动的维护,难度可想而知。最难以忍受的是,对这种维护工作的投入,是没有任何价值的……
   
  有一个比较好的解决办法,那就是将访问数据库的代码全部都放在一个程序文件里。这样,数据库平台一旦发生变化,那么只需要集中修改这一个文件就可以了。我想有点开发经验的人,都会想到这一步的。这种“以不变应万变”的做法其实是简单的“门面模式”的应用。如果把一个网站比喻成一家大饭店,那么“门面模式”中的“门面”,就像是饭店的服务生,而一个网站的浏览者,就像是一个来宾。来宾只需要发送命令给服务生,然后服务生就会按照命令办事。至于服务生经历了多少辛苦才把事情办成?那个并不是来宾感兴趣的事情,来宾们只要求服务生尽快把自己交待事情办完。我们就把listlword.aspx.cs程序就看成是一个来宾发出的命令,而把新加入的lwordtask.cs程序看成是一个饭店服务生,那么来宾发出的命令就是:
   
  “给我读出留言板数据库中的数据,填充到dataset数据集中并显示出来!”
   
  而服务生接到命令后,就会依照执行。而postlword.aspx.cs程序,让服务生做的是:
   
  “把我的留言内容写入到数据库中!”
   
  而服务生接到命令后,就会依照执行。这就是tracelword2!可以在codepackage/tracelword2目录中找到——
   
   
   
  把所有的有关数据访问的代码都放到lwordtask.cs文件里,lwordtask.cs程序文件如下:
   
   
   
  #001 using system;
   
  #002 using system.data;
   
  #003 using system.data.oledb; // 需要操作 access 数据库
   
  #004 using system.web;
   
  #005
   
  #006 namespace tracelword2
   
  #007 {
   
  #008 /// <summary>
   
  #009 /// lwordtask 数据库任务类
   
  #010 /// </summary>
   
  #011 public class lwordtask
   
  #012 {
   
  #013 // 数据库连接字符串
   
  #014 private const string db_conn=@"provider=microsoft.jet.oledb.4.0;
   
  data source=c:\dbfs\tracelworddb.mdb";
   
  #015
   
  #016 /// <summary>
   
  #017 /// 读取数据库表 lword,并填充 dataset 数据集
   
  #018 /// </summary>
   
  #019 /// <param name="ds">填充目标数据集</param>
   
  #020 /// <param name="tablename">表名称</param>
   
  #021 /// <returns>记录行数</returns>
   
  #022 public int listlword(dataset ds, string tablename)
   
  #023 {
   
  #024 string cmdtext="select * from [lword] order by [lwordid] desc";
   
  #025
   
  #026 oledbconnection dbconn=new oledbconnection(db_conn);
   
  #027 oledbdataadapter dbadp=new oledbdataadapter(cmdtext, dbconn);
   
  #028
   
  #029 int count=dbadp.fill(ds, tablename);
   
  #030
   
  #031 return count;
   
  #032 }
   
  #033
   
  #034 /// <summary>
   
  #035 /// 发送留言信息到数据库
   
  #036 /// </summary>
   
  #037 /// <param name="textcontent">留言内容</param>
   
  #038 public void postlword(string textcontent)
   
  #039 {
   
  #040 // 留言内容不能为空
   
  #041 if(textcontent==null || textcontent=="")
   
  #042 throw new exception("留言内容为空");
   
  #043
   
  #044 string cmdtext="insert into [lword]([textcontent]) values(@textcontent)";
   
  #045
   
  #046 oledbconnection dbconn=new oledbconnection(db_conn);
   
  #047 oledbcommand dbcmd=new oledbcommand(cmdtext, dbconn);

   
  #048
   
  #049 // 设置留言内容
   
  #050 dbcmd.parameters.add(new oledbparameter("@textcontent", oledbtype.longvarwchar));
   
  #051 dbcmd.parameters["@textcontent"].value=textcontent;
   
  #052
   
  #053 try
   
  #054 {
   
  #055 dbconn.open();
   
  #056 dbcmd.executenonquery();
   
  #057 }
   
  #058 catch
   
  #059 {
   
  #060 throw;
   
  #061 }
   
  #062 finally
   
  #063 {
   
  #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()
   
  #047 {
   
  #048 dataset ds=new dataset();
   
  #049 (new lwordtask()).listlword(ds, @"lwordtable");
   
  #050
   
  #051 m_lwordlistctrl.datasource=ds.tables[@"lwordtable"].defaultview;
   
  #052 m_lwordlistctrl.databind();
   
  #053 }
   
  ...
   
   
   
  原来的postlword.aspx.cs文件也应作以修改,post_serverclick函数被修改成:
   
   
   
  ...
   
  #048 private void post_serverclick(object sender, eventargs e)
   
  #049 {
   
  #050 // 获取留言内容
   
  #051 string textcontent=this.m_txtcontent.value;
   
  #052
   
  #053 (new lwordtask()).postlword(textcontent);
   
  #054
   
  #055 // 跳转到留言显示页面
   
  #056 response.redirect("listlword.aspx", true);
   
  #057 }
   
  ...
   
   
   
    从前面的程序段中可以看出,listlword.aspx.cs和postlword.aspx.cs这两个文件已经找不到和数据库相关的代码了。只看到一些和lwordtask类有关系的代码,这就符合了“设计模式”中的一种重要原则:“迪米特法则”。“迪米特法则”主要是说:让一个“类”与尽量少的其它的类发生关系。在tracelword1中,listlword.aspx.cs这个类和oledbconnection及oledbdataadapter都发生了关系,所以它破坏了“迪米特法则”。利用一个“中间人”是“迪米特法则”解决问题的办法,这也是“门面模式”必须遵循的原则。下面就引出这个lwordtask门面类的示意图:

TOP

返回顶部
AYBlue

Processed in 0.047831 second(s), 7 queries.

当前时区 GMT+8, 现在时间是 2009-1-10 11:17 京ICP备06054220号

清除 Cookies - 联系我们 - 163K.com - Archiver - WAP