论坛交流
首页办公自动化| 网页制作| 平面设计| 动画制作| 数据库开发| 程序设计| 全部视频教程
应用视频: Windows | Word2007 | Excel2007 | PowerPoint2007 | Dreamweaver 8 | Fireworks 8 | Flash 8 | Photoshop cs | CorelDraw 12
编程视频: C语言视频教程 | HTML | Div+Css布局 | Javascript | Access数据库 | Asp | Sql Server数据库Asp.net  | Flash AS
当前位置 > 文字教程 > Asp.net教程
Tag:静态页面,treeview,gridview,repeater,dataset,sqldatareader,ado.net,上传,三层,ajax,xml,留言本,新闻发布,商城,注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,触发器,socket,form认证,登录,视频教程

Asp.net"三层结构"原理与用意学习入门教程(五)

文章类别:Asp.net | 发表日期:2008-10-31 13:22:56

烹制土豆炖牛肉盖饭方法论的统一——接口实现

怎么实现“烹制土豆烧牛肉盖饭方法论”的统一呢?答案是应用接口。在TraceLWord6中,新建了一个DbTask项目,里面只有一个ILWordTask.cs程序文件,在这里定义了一个接口。DbTask项目应该属于“抽象的数据访问层”。更完整的代码,可以在CodePackage/TraceLWord6目录中找到——

 

 

DbTask项目中的ILWordTask.cs内容如下:

 

#001 using System;

#002

#003 using TraceLWord6.Classes;     // 引用实体规范层

#004

#005 namespace TraceLWord6.DbTask

#006 {

...

#010    public interface ILWordTask

#011    {

#012        // 获取留言信息

#013        LWord[] ListLWord();

#014

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

#016        void PostLWord(LWord newLWord);

#017    }

#018 }


AccessTask项目中的LWordTask.cs需要做出修改:

 

...

#007 using TraceLWord6.Classes;     // 引用实体规范层

#008 using TraceLWord6.DbTask;      // 引用抽象的数据访问层

#009

#010 namespace TraceLWord6.AccessTask

#011 {

...

#015    public class LWordTask : ILWordTask // 实现了ILWordTask接口

#016    {

...

#024        public LWord[] ListLWord()...

...

#071        public void PostLWord(LWord newLWord)...

...

#099    }

#100 }

 

SqlServerTask项目中的LWordTask.cs需要做出修改:

 

...

#007 using TraceLWord6.Classes;     // 引用实体规范层

#008 using TraceLWord6.DbTask;      // 引用抽象的数据访问层

#009

#010 namespace TraceLWord6.SqlServerTask

#011 {

...

#015    public class LWordTask : ILWordTask // 实现了ILWordTask接口

#016    {

...

#024        public LWord[] ListLWord()...

...

#071        public void PostLWord(LWord newLWord)...

...

#100    }

#101 }

 

  AccessTask项目中的LWordTask类实现了ILWordTask接口,那么就必须覆写ListLWordPostLWord这两个函数。SqlServerTask项目中的LWordTask类也实现了ILWordTask接口,那么就也必须覆写ListLWordPostLWord这两个函数。这两个类对共同的接口ILWordTask的实现,使这两个类得到空前的统一。这对于求根溯源,向上转型也是很有帮助的。
DALFactory
项目中的DbTaskDriver.cs文件也要作以修改:

 

...

#026        public ILWordTask DriveLWordTask()

#027        {

#028            // 获取程序集名称

#029            string assemblyName=ConfigurationSettings.AppSettings["AssemblyName"];

#030            // 获取默认构造器名称

#031            string constructor=ConfigurationSettings.AppSettings["Constructor"];

#032

#033            // 建立 ILWordTask 对象实例

#034            return (ILWordTask)Assembly.Load(assemblyName).CreateInstance(constructor,

false);

...

 

  因为AccessTask项目中的LWordTask类和SqlServerTask项目中的LWordTask类,都实现了ILWordTask接口。那么,像行#034这样的转型是绝对成立的。而且转型后的对象,一定含有ListLWordPostLWord这两个函数。InterService项目中的LWordService.cs程序文件应该作以修改,中间业务层只依赖于一个抽象的数据访问层。这样,修改具体的数据访问层就不会影响到它了:

 

...

#008 namespace TraceLWord6.InterService

#009 {

...

#013    public class LWordService

#014    {

#015        /// <summary>

#016        /// 读取 LWord 数据表,返回留言对象数组

#017        /// </summary>

#018        /// <returns></returns>

#019        public LWord[] ListLWord()

#020        {

#021            return (new DbTaskDriver()).DriveLWordTask().ListLWord();

#022        }

#023

#024        /// <summary>

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

#026        /// </summary>

#027        /// <param name="newLWord">留言对象</param>

#028        public void PostLWord(LWord newLWord)

#029        {

#030            (new DbTaskDriver()).DriveLWordTask().PostLWord(newLWord);

#031        }

#032    }

#033 }


一次完整愉快的旅行

就让我们以ListLWord.aspx页面开始,进行一次完整愉快的旅行,看清TraceLWord6的运行全过程。当用浏览ListLWord.aspx页面时,服务器首先会调用ListLWord.aspx.cs文件:

 

...

#021        // 留言列表控件

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

#023

#024        /// <summary>

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

#026        /// </summary>

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

#028        {

#029            LWord_DataBind();

#030        }

...

#045        /// <summary>

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

#047        /// </summary>

#048        private void LWord_DataBind()

#049        {

#050            m_lwordListCtrl.DataSource=(new LWordService()).ListLWord();

#051            m_lwordListCtrl.DataBind();

#052        }

...

 

调用InterService名称空间中的LWordService

 

...

#008 namespace TraceLWord6.InterService

#009 {

...

#013    public class LWordService

#016        /// 读取 LWord 数据表,返回留言对象数组

#017        /// </summary>

#018        /// <returns></returns>

#019        public LWord[] ListLWord()

#020        {

#021            return (new DbTaskDriver()).DriveLWordTask().ListLWord();

#022        }

...

#032    }

#033 }


通过数据访问层工厂来制造对象实例,而工厂类

DbTaskDriver需要读取网站应用程序中的:

Web.Config文件。这里应用了.NET反射机制。

 

...

#007 namespace TraceLWord6.DALFactory

#008 {

...

#012    public class DbTaskDriver

#013    {

...

#023        /// <summary>

#024        /// 驱动数据库任务对象实例

#025        /// </summary>

#026        public ILWordTask DriveLWordTask()

#027        {

#028            // 获取程序集名称

#029            string assemblyName=ConfigurationSettings.AppSettings["AssemblyName"];

#030            // 获取默认构造器名称

#031            string constructor=ConfigurationSettings.AppSettings["Constructor"];

#032

#033            // 建立 ILWordTask 对象实例

#034            return (ILWordTask)Assembly.Load(assemblyName).CreateInstance(constructor,

false);

#035        }

#036    }

#037 }

 

根据配置文件,制造TraceLWord6.SqlServerTask.LWordTask对象

 

...

#010 namespace TraceLWord6.SqlServerTask

#011 {

...

#015    public class LWordTask : ILWordTask

#016    {

...

#020        /// <summary>

#021        /// 读取 LWord 数据表,返回留言对象数组

#022        /// </summary>

#023        /// <returns></returns>

#024        public LWord[] ListLWord()...

...

#100    }

#101 }


最后按照页面上的代码样式绑定数据:

 

...

#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>

...

 

至此为止一个简单的三层结构Web应用程序的执行全过程已经尽显在你眼前。执行顺序其实并不复杂。

 

加入商业规则

“商业规则”,是商业活动中的特殊规则。例如:我们去一家超市买东西,这家超市规定:凡是一次消费金额在2000元以上的顾客,可以获得一张会员卡。凭借这张会员卡,下次消费可以获得积分和享受9折优惠。“商业规则”主旨思想是在表达事与事之间,或者是物与物之间,再或者是事与物之间的关系,而不是事情本身或物质本身的完整性。再例如:一个用户在一个论坛进行新用户注册,该论坛系统规定,新注册的用户必须在4个小时之后才可以发送主题和回复主题。4个小时之内只能浏览主题。这也可以视为一种商业规则。但是,例如:电子邮件地址必须含有“@”字符;用户昵称必须是由中文汉字、英文字母、数字或下划线组成,这些都并不属于商业规则,这些应该被划作“实体规则”。它所描述的是物质本身的完整性。

TraceLWord7中,商业规则是由Rules项目来实现的。其具体的商业规则是:

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

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

这两个条件必须同时满足。更完整的代码,可以在CodePackage/TraceLWord7目录中找到——

那么,商业规则层和中间业务层有什么区别吗?其实本质上没有太大的区别,只是所描述的功能不一样。一个是功能逻辑实现,另外一个则是商业逻辑实现。另外,中间业务层所描述的功能逻辑通常是不会改变的。但是商业逻辑却会因为季节、消费者心理、资金费用等诸多因素而一变再变。把易变的部分提取出来是很有必要的。

 

LWordRules.cs文件内容:

 

#001 using System;

#002

#003 using TraceLWord7.Classes;

#004 using TraceLWord7.DALFactory;

#005 using TraceLWord7.DbTask;

#006

#007 namespace TraceLWord7.Rules

#008 {

#009    /// <summary>

#010    /// LWordRules 留言规则

#011    /// </summary>

#012    public class LWordRules

#013    {


#014        /// <summary>

#015        /// 验证是否可以发送新留言

#016        /// </summary>

#017        /// <returns></returns>

#018        public static bool CanPostLWord()

#019        {

...

#027            DateTime currTime=DateTime.Now;

#028

#029            // 每天上午 09 时之后到 11 时之前可以留言,

#030            // 下午则是 13 时之后到 17 时之前可以留言

#031            if(currTime.Hour<=8 || (currTime.Hour>=11 && currTime.Hour<=12) || currTime.Hour>=17)

#032                return false;

#033

#034            // 获取当天的留言个数

#035            LWord[] lwords=(new DbTaskDriver()).DriveLWordTask().ListLWord(

#036                currTime.Date, currTime.Date.AddDays(1));

#037

#038            // 如果当天留言个数小于 40,则可以继续留言

#039            if(lwords==null || lwords.Length<40)

#040                return true;

#041

#042            return false;

#043        }

#044    }

#045 }

 

LWordService.cs文件中,要加入这样的规则:

 

#025        /// <summary>

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

#027        /// </summary>

#028        /// <param name="newLWord">留言对象</param>

#029        public void PostLWord(LWord newLWord)

#030        {

#031            if(!LWordRules.CanPostLWord())

#032                throw new Exception("无法发送新留言,您违反了留言规则");

#033

#034            (new DbTaskDriver()).DriveLWordTask().PostLWord(newLWord);

#035        }

 

在发送留言之前,调用“商业规则层”来验证当前行为是否有效?如果无效则会抛出一个异常。
“三层结构”的缺点

有些网友在读完这篇文章前作之后,对我提出了一些质疑,这提醒我文章至此还没有提及“三层结构”的缺点。“三层结构”这个词眼似乎一直都很热门,究其原因,或许是这种开发模式应用的比较普遍。但是“三层结构”却并不是百试百灵的“万灵药”,它也存在着缺点。下面就来说说它的缺点……

“三层结构”开发模式的一个非常明显的缺点就是其执行速度不够快。当然这个“执行速度”是相对于非分层的应用程序来说的。从文中所给出的时序图来看,也明显的暴露了这一缺点。TraceLWord1TraceLWord2没有分层,直接调用的ADO.NET所提供的类来获取数据。但是,TraceLWord6确要经过多次调用才能获取到数据。在子程序模块程序没有返回时,主程序模块只能处于等待状态。所以在执行速度上,留言板的版本越高,排名却越靠后。“三层结构”开发模式,不适用于对执行速度要求过于苛刻的系统,例如:在线订票,在线炒股等等……它比较擅长于商业规则容易变化的系统。

“三层结构”开发模式,入门难度够高,难于理解和学习。这是对于初学程序设计的人来说的。以这种模式开发出来的软件,代码量通常要稍稍多一些。这往往会令初学者淹没在茫茫的代码之中。望之生畏,对其产生反感,也是可以理解的……

其实,无论哪一种开发模式或方法,都是有利有弊的。不会存在一种“万用法”可以解决任何问题。所以“三层结构”这个词眼也不会是个例外!是否采用这个模式进行系统开发,要作出比较、权衡之后才可以。切忌滥用——

视频教程列表
文章教程搜索
 
Asp.net推荐教程
Asp.net热门教程
看全部视频教程
购买方式/价格
购买视频教程: 咨询客服
tel:15972130058