当前位置: 首页 > 科技观察

学习之路:项目整体框架搭建简单

时间:2023-03-15 16:15:27 科技观察

最近刚学了一些asp.netmvc的知识,所以想拿个小项目来实践一下,提高自己的编码能力和思维能力。这里以前做事很简单。我直接用那套动态软件生成代码,生成了一个简单的三层结构作为项目的整体框架。数据库访问层使用ado.net。这样做感觉很麻烦。更改数据库,需要在数据库中添加一个表或者在表中添加某个字段,或者使用orm框架访问数据库而不使用ado.net等,这样就需要启动整个项目.为了解决这些问题,我们需要重新思考我们的构建方式。Aboutthedatabaseaccesslayer数据库访问驱动层--大家都知道EF、NH、Ado.net或者你自己实现。这些都是我们访问数据库或者对数据库进行操作的桥梁。当然,数据库也可以是不同的数据库。这些是根据项目要求确定的。至于选择哪一种,要视情况而定。这里我使用EF--model-first。我直接在edmx中设计模型,然后生成实体和数据库,如下,做了一个简单的权限管理(还没完全实现)。。数据库访问实现层很简单。就是传统意义上的BLL层。很久以前,我是一个实体,写了5个crud的基本操作。现在发现还不错2,真心觉得越学越少代码,,,,这里直接定义一个基类,然后让其他实体类继承,,,真的发现更好了2之前——哈哈publicclassBaseRepository:IDAL。IBaseRepositorywhereT:class{privateDbContextcontainer=EFContentFactory.GetCurrentContext();#region添加publicTAddEntity(Tentity){container.Set().Add(entity);返回实体;}#endregion#regiondeletepublicboolDeleteEntity(Tentity){container.Set().Attach(entity);container.Entry(entity).State=EntityState.Deleted;返回真;}#endregion#region修改publicboolUpdateEntity(Tentity){container.Set()。附加(实体);container.Entry(entity).State=EntityState.Modified;返回真;}#endregion#region查询publicIQueryableGetEntities(FunclambdaWhere){IQuerybleentities=container.Set().Where(lambdaWhere).AsQueryable();回归实体;}#endregion#region分页publicIQueryableGetEntitiesByPageIndex(intpageIndex,intpageSize,outinttotalCount,FunclambdaWhere,FuncorderByRole,boolddescending){vartemp=container.Set().Where(lambdaWhere).AsQueryable();totalCount=temp.Count();如果(降序){temp=temp.OrderByDescending(orderByRole).Skip(pageSize*(pageIndex-1)).Take(pageSize).AsQueryable();}else{temp=temp.OrderBy(orderByRole).Skip(pageSize*(pageIndex-1)).Take(pageSize).AsQueryable();}返回温度;}#endregion}至此,我以为我的数据库访问层写完了,接下来就可以写业务逻辑层了,其实不然。想一想,如果你要换数据库,或者换成ef或者ado.net,如果按照老办法,整个项目的每一层都需要换,大大增加了工作量。这里我们可以做一个技巧,将数据访问层抽象出一个层,这需要使用接口。IDAL.IBaseRepository一般想想我们的bll层。如果没有接口,我们可以直接写dal.xxrepository=newxxrepository();如前所述,可维护性和可替换性大大降低。我们现在可以写IDAL.xxrepository=newxxrepository()。这样,当我们替换DAL层时,BLL层root不需要关心你如何实现它。这个非常重要。接口相当于一个契约,约束了你必须实现哪些功能。如果我们要添加功能,直接在界面上添加即可。该接口需要是部分接口。像上面我给的代码,基类需要接口,子类也需要接口。这样,我们抽象出一个数据库接口层。抽象工厂和简单工厂也可以从业务层和数据库访问层进行抽象,这里要用到工厂——其实很简单,从工厂类中取出dal层的类,返回IDAL接口returnnewRoleRepository();}}}那么业务层在拿到接口的时候就不需要关心接口如何实现了。这是另一层抽象。当然你也可以使用抽象工厂,通过反射和配置加缓存的方式来实现,但是一般来说,简单的工厂就够了,这里相当于一个数据库访问层的入口。业务逻辑层的基类和子类 当我们实体模型太多的时候,如果没有基类,我们就得写一堆重复的东西,我们现在要把这些重复的东西进入基类让我们实现,像Dal层,我们定义了一个基类,但是在BLL层我们会遇到一个问题,如何从IDAL.IBaseRepository中获取工厂接口...想想it...我们的子类就可以知道自己需要的接口了---我们可以搞个诡计,让父类做一个抽象类,定义一个抽象方法,然后让子类重写这个方法,在类中调用constructor,因为我们必须使用这个接口,所以我们必须在constructor()中publicabstractclassBaseService:IBLL.IBaseServicewhereT:class,new{publicBaseService(){GetInstance();}protectedIDAL.IDbSession_DbSession=DbSeesionFactory.GetSession();受保护edIDAL.IBaseRepositoryCurrentRepository{get;set;}publicabstractvoidGetInstance();publicIQueryableGetEntities(FunclambdaWhere){//_DbSession.SavaChanges();returnCurrentRepository.GetEntities(lambdaWhere);}publicbool(DeleteETentity){CurrentRepository.DeleteEntity(entity);return_DbSession.SaveChanges()>0;}publicboolUpdateEntity(Tentity){CurrentRepository.UpdateEntity(entity);return_DbSession.SaveChanges()>0;(实体);_DbSession.SaveChanges();返回;}publicIQueryableGetEntitiesByPageIndex(intpageIndex,intpageSize,outinttotalCount,FunclambdaWhere,FuncorderByRole,boolddescending){returnCurrentIndexBageRepository.GetEvent(pageIndex,pageSize,outtotalCount,lambdaWhere,orderByRole,降序));其他业务层也需要从接口抽象出一层作为约束,这样ui层就不用关心你的业务层是怎么实现的了……另一种实现数据库入口DBSession的方式我们来看看第一节课,dbsession里面有属性,都是接口,对应接口对应的实现类,两个方法SaveChanges(),和exesql(EF使用的5.0+),返回当前EF线程的savechange()和执行classcontextsql语句的返回值,如何保证当前进程只有一个EF上下文,我们再看一个class{//get{returnnewRoleRepository();}//}//publicIDAL.IUserInfoRepositoryUserInfoRepository//{//get{returnnewUserInfoRepository();}//}#endregionpublicintSaveChanges(){returnEFContentFactory.GetCurrentContext().SaveChanges();}publicintExcuteSql(stringstrSql,System.Data.Objects.ObjectParameter[]parameters){returnEFContentFactory.GetCurrentContext().Database.ExecuteSqlCommand(strSql,parameters);}}publicclassEFContentFactory{publicstaticDbContextGetCurrentContext(){DbContextobj=CallContext.GetData("DbContext")asDbjContext;if(null){obj=newModel.DataContainer();CallContext.SetData("DbContext",obj);}返回对象;}}CallContext是一个类似线程局部存储的方法调用专用集合对象,为每个逻辑执行线程提供支持独特的数据插槽数据槽不在其他逻辑线程上的调用上下文之间共享。这是一段摘自msdn的文章。它有几种方法。这里我们使用setdata和getdata来保证上下文线程是唯一的。同样,我们让它在工厂中接口实现--publicclassDbSeesionFactory{///

///保证线程中的dbsession是唯一的//////publicstaticIDAL.IDbSessionGetSession(){IDAL.IDbSession_dbSession=CallContext.GetData("DbSession")asIDbSession;如果(_dbSession==null){_dbSession=newDbSession();CallContext.SetData("DbSession",_dbSession);}return_dbSession;写法时这么来现实,类似基类添加:protectedIDAL.IDbSession_DbSession=DbSeesionFactory.GetSession();publicpartialclassActionInfoService:BaseService,IBLL.IActionInfoService{publicoverridefoSpositionActionReposition_Instance=();CurrentpartialclassActionInfoService:BaseService,IBLL.IActionInfoService{}}publicpartialclassR_UserInfo_ActionInfoService:BaseService,IBLL.IR_UserInfo_ActionInfoService{publicoverridevoidGetInstance(){CurrentRepository=_DbSession.R_UserInfo_ActionI信息库;}}publicpartialclassRoleService:BaseService,IBLL.IRoleService{publicoverridevoidGetInstance(){CurrentRepository=_DbSession.RoleRepository;}}我们为什么要做这个?比如我们在使用EF的时候,需要在一个方法中操作多个表。不断需要使用上下文,它可以帮助我们做很多事情。直接来_dbsession.savechange()。可以实现批量删除修改等操作。具体来说,我进行了批量删除}return_DbSession.SaveChanges();收获颇多,虽然有些东西不是很懂,但稍微看一下就明白了,分享给大学里一起学习~原文链接:http://www.cnblogs.com/wings/archive/2012/12/03/2798943.html