ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) (1)框架搭建 (2):数据库访问层的设计Demo
前言:这篇博客在数据访问层的基础上面我们继续学习对这个Demo的开发,希望大家都好好理解一下这个Demo的架构,到最后我实现权限的时候我就简单的说一下搭建过程就OK了,因为这个Demo的思想就是按照权限的设计方式去设计的,下面我们开始介绍面向接口的编程思想,如果感觉好的话可以点一下支持,下面我们切入正题。
1.新建面向接口编程的类库
(1)在这篇博客中我们主要针对面向接口进行编程,既然是面向接口,那么我们就必须要在创建一个存放接口的类库,然后创建几个接口,下面我就详细的讲述一下创建这个接口类库和接口类的过程。
(2)首先我们在这个项目下面创建数据库访问接口层的一个类库,起名为:LYZJ.UserLimitMVC.IDAL,然后我们创建三个接口类,依此是:IBaseRepository.cs,IUserInfoRepository,IRoleRepository。我只是这样说的话可能有些人会感觉云里雾里的,所以我这里就将项目的图形放在上面,方便大家理解,如图所示:
(3)下面我们详细来分析LYZJ.UserLimitMVC.IDAL类库下面的三个接口类所实现的功能。
2. LYZJ.UserLimitMVC.IDAL类库中三个接口类的分析
(1)IBaseRepository,在这个基接口中我们封装了所有操作数据库的方法,从另外一种角度来看接口的话接口就是一个约束,我们定义接口约束了操作数据库的方法,下面因为每个数据库实体(UserInfo,RoleInfo)都需要操作数据库的接口,所以我定义了一个基接口用来实现对数据库的访问方法的封装,然后数据库实体只需要继承自这个基接口即可,代码如下:
1 public interface IBaseRepository<T> where T : class, new() 2 3 { 4 5 // 实现对数据库的添加功能,添加实现EF框架的引用 6 7 T AddEntity(T entity); 8 10 11 //实现对数据库的修改功能 12 13 bool UpdateEntity(T entity); 14 15 16 17 //实现对数据库的删除功能 18 19 bool DeleteEntity(T entity); 20 21 22 23 //实现对数据库的查询 --简单查询 24 25 IQueryable<T> LoadEntities(Func<T, bool> whereLambda); 26 27 28 29 /// <summary> 30 31 /// 实现对数据的分页查询 32 33 /// </summary> 34 35 /// <typeparam name="S">按照某个类进行排序</typeparam> 36 37 /// <param name="pageIndex">当前第几页</param> 38 39 /// <param name="pageSize">一页显示多少条数据</param> 40 41 /// <param name="total">总条数</param> 42 43 /// <param name="whereLambda">取得排序的条件</param> 44 45 /// <param name="isAsc">如何排序,根据倒叙还是升序</param> 46 47 /// <param name="orderByLambda">根据那个字段进行排序</param> 48 49 /// <returns></returns> 50 51 IQueryable<T> LoadPageEntities<S>(int pageIndex, int pageSize, out int total, Func<T, bool> whereLambda,bool isAsc, Func<T, S> orderByLambda); 52 53 }
(2)IUserInfoRepository,这个接口只需要实现继承自基接口即可,当继承基接口的时候就实现了基接口中的所有方法,代码如下:
1 public interface IUserInfoRepository:IBaseRepository<UserInfo> 3 { 4 5 }
(3)IRoleRepository,和第(2)个解释一样,代码如下:
1 public interface IRoleRepository:IBaseRepository<Role> 2 3 { 4 5 }
(4)注意:当我们操作IUserInfoRepository和IRoleRepository的时候我们需要添加LYZJ.UserLimitMVC.Model的引用,因为我们要用到数据库实体对象。
3.数据库访问层的重新设计(LYZJ.UserLimitMVC.DAL类库)
(1)角色仓储(RoleRepository)的设计
当我们完成数据访问接口层的时候,这时候我们就要重新修改数据库访问层的数据,因为要用到数据库访问接口层,所以我们要添加数据库接口层的DLL,LYZJ.UserLimitMVC.IDAL。
然后我们的角色仓储要继承数据库访问接口层的角色仓储接口,代码如下:
1 public class RoleRepository : BaseRepository<Role>, IRoleRepository 2 3 { 4 5 }
(2)用户仓储(RoleRepository)的设计,和上面的解释一样,代码如下:
1 public class UserInfoRepository : BaseRepository<UserInfo>, IUserInfoRepository 2 3 { 4 5 }
(3)数据库访问层的设计思路是:先继承基类,在实现接口。上面的实现正是引用了这句话来实现。
注解:数据库访问层我们就说到这里了,如果大家有什么不懂的或者不知道的,可以给我留言,我将在第一时间回复,下面我们开始研究业务逻辑层的实现
4.业务逻辑层(BLL)初探
(1)从开始到现在我们的数据库访问层只能说是暂时告一段路了,因为在后面我们还会修改数据库访问层,我们现在写的代码并不是一直不变的,而是随着写慢慢的我们就会提取出来很多东西进行封装,所以如果你仔细看我博客的话我一直在修改这些代码。
(2)业务逻辑层是什么呢?我相信如果做过asp.net三层架构的用户都是理解的,就是对数据库访问层的封装,在这里我也不详细的解释什么是业务逻辑层了,如果大家不太理解的话可以去百度或者谷歌搜索一下。
(3)下面我们对业务逻辑层开始进行操作
5.业务逻辑层(LYZJ.UserLimitMVC.BLL)的实现
(1)首先我们新建一个UserInfoService类,这个类就是对UserInfo的业务逻辑进行实现(增删改查)。
(2)如果我们要实现业务逻辑层的话,我们就要添加数据库访问层和实体层以及操作Entity FrameWork框架的的DLL,如下:LYZJ.UserLimitMVC.DAL,LYZJ.UserLimitMVC.IDAL,LYZJ.UserLimitMVC.Model,System.Data.Entity。
6.UserInfo业务逻辑类的实现
(1)首先我贴出UserInfo.cs类的代码,在这里我们要仔细的分析一下UserInfo类的代码的实现:
1 namespace LYZJ.UserLimitMVC.BLL 2 3 { 4 5 /// <summary> 6 7 /// UserInfo业务逻辑 8 9 /// </summary> 10 11 public class UserInfoService 12 13 { 14 15 //访问DAL实现CRUD 16 17 //private DAL.UserInfoRepository _userInfoRepository = new UserInfoRepository(); 18 19 private IUserInfoRepository _userInfoRepository = new UserInfoRepository(); 20 21 22 public UserInfo AddUserInfo(UserInfo userInfo) 23 24 { 25 26 return _userInfoRepository.AddEntity(userInfo); 27 28 } 29 30 31 public bool UpdateUserInfo(UserInfo userInfo) 32 33 { 34 35 return _userInfoRepository.UpdateEntity(userInfo); 36 37 } 38 39 } 40 41 }
(2)因为我们的业务逻辑层要用到实体对象,也就是UserInfo,所以这里我们需要添加引用,这个我再上面已经提到过了。业务逻辑层就是去访问数据库访问层(DAL),然后实现对数据库的增删改查,所以我们就需要定义一个数据库访问层的实例:private DAL.UserInfoRepository _ userInfoRepository=new UserInfoRepository();但是如果我们这样做的话就完全的违背了我们说的依赖接口编程,所以我们不建议这么写,既然我们已经有了接口了,那么我们可以依赖接口定义:private IUserInfoRepository _ userInfoRepository=new UserInfoRepository();,那么这两种写法的差别在哪里呢?它们有什么差别呢?下来我大致的说一下:
(3)上面两种定义的区别在哪里
上面这两种写法,可能有的人会认为没有区别,其实不然,这里这样写的区别很大,如果我们在下面有很多方法的话,我们所有的方法都要去调用仓储里面的方法,而这个仓储却是接口实例,跟具体的实现就没有什么关系,也就是说我们业务逻辑层依赖的数据访问层的接口,只要接口不变化,那么下面的代码都是不会变化的,如果某一天我们需要用ADO来实现这个功能的话,我们只需要替换掉new后面的UserInfo仓储,换成ADO.NET实现的仓储,这样的话我们下面的方法都是不需要变化的,这就是所谓的依赖接口编程。只要接口不变化,那么我们下面的代码永远不会变化。
7.不想new UserInfoRepository();仓储,怎么办?
(1)通过上面我们定义接口来实例化对象已经使用了依赖接口的编程,但是现在我还不想new UserInfoRepository();实例,因为这个对象极有可能变化,有可能使用EF实现的仓储,有可能使用ADO实现的仓储,而且我们设计到业务逻辑层的实例都要定义仓储对象,那么当我们实体很多的时候,维护起来非常的不方便,我们需要每个页面的去修改这些东西,所以在这里我们就能够想着使用一种什么方法将这个仓储做为一种参数传递进去,而我们只需要在传递参数的类里面进行维护,下面我们就分析一下如何使用。
(2)遇到变化点,我们就要想办法看能不能封装起来,这里当然可以了,我们将获取此仓储实例的方法放到一个公共的地方,改变的时候直接改变这个公共的地方就行了, 那么这里怎么弄呢?我们首先想到的最简单的就是简单工厂,那么什么是简单工厂呢?其实很简单,我们只要理解只要是工厂,就是为我们创建实例的类,既然我们这里需要一个公共的地方,那么我们就要在LYZJ.UserLimitMVC.DAL这个类库下面添加一个RepositoryFactory类,这个类里面我们建立了一个UserInfoRepository属性,这个静态属性里面就是为我们返回这个仓储即可。那么这时候如果我们想要修改的话就直接去改变UserInfoRepository属性即可
(3) RepositoryFactory类的实现
(1)同我们上面的分析,下面我们实现这个类的代码,代码如下:
1 namespace LYZJ.UserLimitMVC.DAL 2 3 { 4 5 public static class RepositoryFactory 6 7 { 8 9 public static IUserInfoRepository UserInfoRepository 10 11 { 12 13 get { return new UserInfoRepository(); } 14 15 } 16 17 } 18 19 }
(2)然后我们修改业务逻辑层的定义实例化仓储的代码如下:
private IUserInfoRepository _userInfoRepository = RepositoryFactory.UserInfoRepository;
(3)这时候我们就完成了这个仓储的封装,现在我们如果想要替换仓储的话,我们只需要去替换RepositoryFactory中的方法即可,这也就是一个简单的简单工厂,当我们添加上这个简单工厂之后,我们数据库访问层和业务逻辑层之间的依赖就更加的减少了耦合度。
8.小结
(1)到这里这篇博客终于完事了,现在我才知道针对着项目写博客真心不好写,语言组织没有写技术点那么方便,导致我这篇文章写了5个小时,不过功夫不负有心人,终于完事了,相比大家看得时候会比较难懂,如果大家有什么不懂的可以问我,我将这篇博客的代码上传到CSDN中,大家可以去下载一边看代码一边看博客,我想这样大家容易理解。
(2)下面是今天写完这篇博客之后现在的项目架构
(3) 依赖接口编程图纸
最后附项目下载地址:http://download.csdn.net/detail/hanyinglong/5235253
Kencery返回本系列开篇