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

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

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

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

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

“三层结构”是什么?

  “三层结构”一词中的“三层”是指:“表现层”、“中间业务层”、“数据访问层”。其中:

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

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

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

<shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-family: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><img alt="" src="https://p-blog.csdn.net/images/p_blog_csdn_net/Dream6000/1.GIF"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 274.5pt; HEIGHT: 149.25pt" o:ole="" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5CDREAM6~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.emz"></imagedata></shape></span><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 274.5pt; HEIGHT: 149.25pt" o:ole="" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5CDREAM6~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.emz"></imagedata></shape>

<shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 274.5pt; HEIGHT: 149.25pt" o:ole="" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5CDREAM6~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.emz"></imagedata></shape>

  对依赖方向的研究将是本文的重点,数值返回方向基本上是没有变化的。

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

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


功能说明:

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

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

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

字段名称

数据类型

默认值

备注说明

[LWordID]

INT

NOT NULL IDENTITY(1, 1)

留言记录编号

[TextContent]

NText

N’’

留言内容

[PostTime]

DateTime

GetDate()

留言发送时间,默认值为当前时间

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

#001 <%@ Page language="c#" Codebehind="ListLWord.aspx.cs" AutoEventWireup="false"

Inherits="TraceLWord1.ListLWord" %>

#002 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

#003

#004 <html>

#005 <head>

#006 <title>ListLWord</title>

#007 <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">

#008 <meta name="CODE_LANGUAGE" Content="C#">

#009 <meta name=vs_defaultClientScript content="JavaScript">

#010 <meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">

#011 </head>

#012 <body MS_POSITIONING="GridLayout">

#013

#014 <form id="__aspNetForm" method="post" runat="server">

#015

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

#017

#018 <asp:DataList ID="m_lwordListCtrl" Runat="Server">

#019 <ItemTemplate>

#020 <div>

#021 <%# DataBinder.Eval(Container.DataItem, "PostTime") %>

#022 <%# DataBinder.Eval(Container.DataItem, "TextContent") %>

#023 </div>

#024 </ItemTemplate>

#025 </asp:DataList>

#026

#027 </form>

#028

#029 </body>

#030 </html>

以最普通的设计方式制作留言板,效率很高。

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

#001 using System;

#002 using System.Collections;

#003 using System.ComponentModel;

#004 using System.Data;

#005 using System.Data.OleDb; // 需要操作 Access 数据库

#006 using System.Drawing;

#007 using System.Web;

#008 using System.Web.SessionState;

#009 using System.Web.UI;

#010 using System.Web.UI.WebControls;

#011 using System.Web.UI.HtmlControls;

#012

#013 namespace TraceLWord1

#014 {

#015 /// <summary>

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

#017 /// </summary>

#018 public class ListLWord : System.Web.UI.Page

#019 {

#020 // 留言列表控件

#021 protected System.Web.UI.WebControls.DataList m_lwordListCtrl;

#022

#023 /// <summary>

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

#025 /// </summary>

#026 private void Page_Load(object sender, System.EventArgs e)

#027 {

#028 LWord_DataBind();

#029 }

#030

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

#032 override protected void OnInit(EventArgs e)

#033 {

#034 InitializeComponent();

#035 base.OnInit(e);

#036 }

#037

#038 private void InitializeComponent()

#039 {

#040 this.Load+=new System.EventHandler(this.Page_Load);

#041 }

#042 #endregion

#043

#044 /// <summary>

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

#046 /// </summary>

#047 private void LWord_DataBind()

#048 {

#049 string mdbConn=@"PROVIDER=Microsoft.Jet.OLEDB.4.0;

DATA Source=C:\DbFs\TraceLWordDb.mdb";

#050 string cmdText=@"SELECT * FROM [LWord] ORDER BY [LWordID] DESC";

#051

#052 OleDbConnection dbConn=new OleDbConnection(mdbConn);

#053 OleDbDataAdapter dbAdp=new OleDbDataAdapter(cmdText, dbConn);

#054

#055 DataSet ds=new DataSet();

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

#057

#058 m_lwordListCtrl.DataSource=ds.Tables[@"LWordTable"].DefaultView;

#059 m_lwordListCtrl.DataBind();

#060 }

#061 }

#062 }

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

#001 <%@ Page language="c#" Codebehind="PostLWord.aspx.cs" AutoEventWireup="false"

Inherits="TraceLWord1.PostLWord" %>

#002 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

#003

#004 <html>

#005 <head>

#006 <title>PostLWord</title>

#007 <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">

#008 <meta name="CODE_LANGUAGE" Content="C#">

#009 <meta name=vs_defaultClientScript content="JavaScript">

#010 <meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">

#011 </head>

#012 <body MS_POSITIONING="GridLayout">

#013

#014 <form id="__aspNetForm" method="post" runat="server">

#015

#016 <textarea id="m_txtContent" runat="Server" rows=8 cols=48></textarea>

#017 <input type

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值