ASp.net 剖析三层架构 |
本文不是从 实际的角度来探讨三层架构,而是用一个示例来介绍如何建设一个三层架构的 名目,并 注明 名目中各个文件所处的 品位与作用 。写本文的 目标,不是为了 注明自己的这个 步骤有多对,别人的 确定不对,而是 盼望给那些初学三层架构却不知从何 动手的朋友提供丝毫协助 。由于网上的文章,大多是 重视 实际的介绍,而 忽略了具体的 实际 利用,或者有示例但讲得不透彻 。招致看了之后, 实际上又学习了一遍,但还是不晓得代码怎么写 。所以想从这个方面 动手写一下,让 向来没做过三层架构的初学者也能照猫画虎,写出代码来 。文章表述的是小编个人对三层架构的 意识, 确定有许多缺乏的地方, 欢送大家 教正,小弟也会依据反馈来 批改这篇文章 。文中的代码是伪代码,仅用来 注明思路 。 一提三层架构,大家都晓得是 体现层(UI),业务逻辑层(BLL)和数据 拜访层(DAL),并且每层如何细分也都有众多的 步骤 。但具体代码怎么写,到底那些文件算在哪一层,却是模含糊糊的 。下面用一个 方便的例子来 统率大家实战三层架构的 名目,这个例子惟独一个 性能,便是消费者的 方便治理 。 首先 构建一个空白解决 方案,增加如下 名目及文件 1、增加ASP.NET Web Application 名目,命名为UI,新建Web Form类型文件User.aspx(含User.aspx.cs) 2、增加ClassLibrary 名目,命名为BLL,新建Class类型文件UserBLL.cs 3、增加ClassLibrary 名目,命名为DAL,新建Class类型文件UserDAL.cs.增加SQLHelper 引用 。(这个是微软的数据 拜访类,也 可以不用,直接编写全部的数据 拜访代码 。我一般用自己写的数据 拜访类DataAccessHelper ) 。 4、增加ClassLibrary 名目,命名为Model,新建Class类型文件UserModel.cs 5、增加ClassLibrary 名目,命名为IDAL,新建Interface类型文件IUserDAL.cs 6、增加ClassLibrary 名目,命名为ClassFactory 相信大家已经看出来了,这个和Petshop的示例没什么区别,并且更 方便,由于在下也是通过Petshop学习三层架构的 。但一些朋友关于这几个 名目所处的 品位,以及它们中间的关系,可能 比较含糊,这里一一 注明一下: 1、User.aspx和User.aspx.cs 这两个文件(以及文件所属的 名目,下面也是如此,不再 反复强调了)都属于 体现层 部分 。User.aspx 比较好 了解,由于它便是显示页面了 。User.aspx.cs有些人觉得不应该算,而是要划到业务逻辑层中去 。假如不做分层的话,那么让User.aspx.cs来 解决业务逻辑,甚至操作数据库都没什么问题,然而做分层的话,这样就不应该了 。在分层 构造中,User.aspx.cs仅应该 解决与显示有关的内容,其它 部分都不应该 波及 。 举例:我们实现用列表 模式显示消费者的 性能,那么提 守信息的工作是由BLL来做的,UI(本例中是User.aspx.cs)调用BLL得到UserInfo后,通过代码绑定到User.aspx的数据控件上,就实现了列表的显示 。在此过程中User.aspx.cs对UI没有起到什么作用,仅是用来传递数据,并且由于实际编码中大 部分状况都是如此的实现,所以使有些人觉得User.aspx.cs不应该算UI,而应该并入BLL负责逻辑 解决 。 接续往下看,这时提出了一个新需要,要求在每个消费者的前面加一个图标, 活泼地 体现出消费者的性别,并且不满18岁的用儿童图标 示意 。这个需要的实现,就轮到User.aspx.cs来做了,这种状况下User.aspx.cs才算有了真正的 用处 。 2、NewBLL.cs 增加如下 步骤: public IList<UserInfo> GetUsers():返回全部的消费者信息列表 public UserInfo GetUser(int UserId):返回指定消费者的 详尽信息 public bool AddUser(UserInfo User):新增消费者信息 public bool ChangeUser(UserInfo User):更新消费者信息 public void RemoveUser(int UserId):移除消费者信息 此文件就属于业务逻辑层了,专门用来 解决与业务逻辑有关的操作 。可能有众多人觉得这一层唯一的 用处,便是把 体现层传过来的数据转发给数据层 。这种状况 确切众多,但这不得不 注明 名目 比较 方便,或者 名目 本身与业务的关系 联合的不密切( 比方目前 比较 风行的MIS),所以造成业务层无事可做,只起到了一个转发的作用 。但这不代表业务层可有可无,随着项 目标增大,或者业务关系 比较多,业务层就会体现出它的作用来了 。 此处最可能造成 舛误的,便是把数据操作代码划在了业务逻辑层,而把数据库作为了数据 拜访层 。 举例:有些朋友觉得BLL层 意思不大,只是将DAL的数据提上来就转发给了UI,而未作任何 解决 。看一下这个例子 BLL层 SelectUser(UserInfo userInfo)依据传入的username或email得到消费者 详尽信息 。 IsExist(UserInfo userInfo)推断指定的username或email是不是存在 。 而后DAL也相应提供 步骤共BLL调用 SelectUser(UserInfo userInfo) IsExist(UserInfo userInfo) 这样BLL 确切只起到了一个传递的作用 。 但假如这样做: BLL.IsExist(Userinfo userinfo) { UerInfo user = DAL.SelectUser(User); return (userInfo.Id != null); } 那么DAL就无需实现IsExist() 步骤了,BLL中也就有了逻辑 解决的代码 。 3、UserModel.cs 实体类,这个东西,大家可能觉得不好分层 。包含我以往在内,是这样 了解的:UI?àModel?àBLL?àModel?àDAL,如此则认为Model在各层中间起到了一个数据传输的桥梁作用 。不过在这里,我们不是把 事件想 方便,而是想复杂了 。 Model是什么?它什么也不是!它在三层架构中是可有可无的 。它其实便是面向对象编程中最 根本的东西:类 。一个桌子是一个类,一条新闻也是一个类,int、string、doublie等也是类,它仅仅是一个类而已 。 这样,Model在三层架构中的位置,和int,string等变量的地位就一样了,没有其它的 目标,仅用于数据的存储而已,只是它存储的是复杂的数据 。所以假如你的 名目中对象都十分 方便,那么不用Model而直接传递多个参数也能做成三层架构 。 那为何还要有Model呢,它的 好处是什么呢 。下面是思量一个问题时想到的,插在这里: Model在各层参数传递时到底能起到做大的作用? 在各层间传递参数时, 可以这样: AddUser(userId,userName,userPassword,…,) 也 可以这样: AddUser(userInfo) 这两种 步骤那个好呢 。 一览无余, 确定是第二种要好众多 。 什么时候用一般变量类型(int,string,guid,double)在各层中间传递参数,什么 使用Model传递?下面几个 步骤: SelectUser(int UserId) SelectUserByName(string username) SelectUserByName(string username,string password) SelectUserByEmail(string email) SelectUserByEmail(string email,string password) 可以归纳为: SelectUser(userId) SelectUser(user) 这里用user这个Model对象囊括了username,password,email这三个参数的四种组合模式 。UserId其实也 可以合并到user中,但 名目中其它BLL都实现了带有id参数的接口,所以这里也保留这一项 。 传入了userInfo,那如何 解决呢,这个就需要依照先后的顺序了,有具体代码决定 。 这里按这个顺序 解决 首先看是不是同时 存在username和password, 而后看是不是同时 存在email和password, 而后看是不是有username, 而后看是不是有email. 顺次 解决 。 这样,假如以后增加一个新内容,会员卡(number),则无需更改接口, 惟独在DAL的代码中增加对number的 支撑就行, 而后前台增加会员卡一项内容的 体现与 解决即可 。 4、UserDAL.cs public IList<UserInfo> SelectUsers():返回全部的消费者信息列表 public UserInfo SelectUser(int UserId):返回指定消费者的相信信息 public bool InsertUser(UserInfo User):新增消费者信息 public bool UpdateUser(UserInfo User):更新消费者信息 public void DeleteUser(int UserId):移除消费者信息 众多人最闹不清的便是数据 拜访层,到底那 部分才算数据 拜访层呢?有些认为数据库便是数据 拜访层,这是对定义没有搞清晰,DAL是数据 拜访层而不是数据存储层, 因此数据库不可能是这一层的 。也有的把SQLHelper(或其同类作用的组件)作为数据 拜访层,它又是一个可有可无的东西,SQLHelper的作用是削减 反复性编码, 普及编码效率, 因此假如我习惯在乎效率或 使用一个非数据库的数据源时, 可以 放弃SQLHelper,一个 可以 随便弃置的 部分,又怎么能成为三层架构中的一层呢 。 可以这样定义:与数据源操作有关的代码,就应该放在数据 拜访层中,属于数据 拜访层 5、IUserDAL 数据 拜访层接口,这又是一个可有可无的东西,由于Petshop中带了它和ClassFactory类工厂,所以有些 名目 不管需不需要 支撑多数据源,都把这两个东西做了进来,有的甚至不建ClassFactory而只建了IDAL, 而后"IUserDAL iUserDal = new UserDAL();",不知 意思何在 。这就 彻底是画虎不成反类犬了 。 许多人在这里有一个 误会,那便是 认为存在这样的关系:BLL?àIDAL?àDAL,认为IDAL起到了BLL和DAL中间的桥梁作用,BLL是通过IDAL来调用DAL的 。但实际是 即便你如此编码:"IUserDAL iUserDal = ClassFacotry.CreateUserDAL();",那么在执行"iUserDal.SelectUsers()"时,其实还是执行的UserDAL实例,而不是IUserDAL实例,所以IDAL在三层中的位置是与DAL平级的关系 。 通过上面的介绍, 根本上将三层架构的 品位 构造 注明了 。其实,本人有一个推断三层架构是不是 标准的 步骤,那便是将三层中的任意一层 彻底替换,都不会对其它两层造成影响,这样的 构造 根本就 相符三层 标准了( 固然实现起来 比较难^_^) 。例如假如将 名目从B/S改为C/S(或相反),那么除了UI以外,BLL与DAL都不用 改变;或者将SQLServer改为Oracle, 惟独替换SQLServerDAL到OracleDAL,无需其它操作等等 。 原来想在文中加入一些具体的代码的,但觉得不是很必要,假如大家觉得需要的话,我再补充吧 。 总结:不要由于某个层对你来说没用,或者实现起来特殊 方便,就认为它没有必要,或者摒弃它,或者挪作它用 。 惟独进行了分层, 无论是几层,每一层都要有明确的 目标和 性能实现,而不要被实际过程所左右,造成同一类文件位于不同层的状况 产生 。也不要浮现同一层实现了不同的 性能的状况 产生 。 |