ITOO框架简单了解
2016-01-22 15:58
381 查看
一、回顾三层
二、D层重构
我们在敲D层的时候,UserDAL和RoleDAL中都包含实现对数据库的操作,也就是增删改查,那么我们可以将这些公共的东西抽象出来实现一个固定的功能的基类(BaseDAL),然后我们对其进行继承操作。BaseDAL
public class BaseRepository<T> where T : class { //创建EF上下文 private LYZJEntities dbLYZJ = new LYZJEntities(); #region 实现对数据库的修改功能+UpdateEntity+王娜+2016年1月9日16:38:30 /// <summary> /// 实现对数据库的修改功能+UpdateEntity+王娜+2016年1月9日16:38:30 /// </summary> /// <param name="entity"></param> /// <returns></returns> public bool UpdateEntity(T entity) { dbLYZJ.Set<T>().Attach(entity); dbLYZJ.Entry<T>(entity).State = EntityState.Modified; return dbLYZJ.SaveChanges() > 0; } #endregion }
针对面向接口编程
三、B层重构
BaseService类在B层中的每个类,都有实例化D层的过程,现在我们将这个过程进行封装,建立一个基类(BaseService)
public abstract class BaseService<T>where T:class,new() { public IDAL.IBaseRepository<T> CurrentRepository { get; set; } //构造函数 public BaseService() { SetCurrentRepository();//构造函数里面去调用,设置当前DAL的抽象 } public abstract void SetCurrentRepository();//必须由子类实现 }
UserInfoService类
public class UserInfoService:BaseService<UserInfo> { public override void SetCurrentRepository() { CurrentRepository = DAL.UserInfoRepository; } public bool UpdateEntity(T entity) { return CurrentReository.UpdateEntity(entity); } }
因为,子类调用哪个D层,只有子类(UserInfoService)清楚,父类(BaseService)不知道,所以,我们调用一个抽象方法public abstract void SetCurrentRepository()让子类自己进行实现;因为我们所有的D层类都间接的继承于IBaseDAL,所以我们可以使用IBaseDAL类接收当前的DAL。
针对面向接口编程
四、B层对于D层的引用
之前,我们是B层直接调用D层,现在我们立一个数据层的统一入口——Factory来进行封装。RepositoryFactory
public class RepositoryFactory { #region 王娜+2016年1月10日16:30:59 public static IUserInfoRepository UserInfoRepository { get { return new UserInfoRepository(); } } #endregion #region 王娜+2016年1月10日16:31:12 public static IRoleRepository RoleRepository { get { return new RoleRepository(); } } #endregion
业务逻辑层实例化D层的代码:
private IUserInfoRepository _userInfoRepository = RepositoryFactory.UserInfoRepository;
五、D层对EF上下文的管理
在此之前,我们先了解一下EF,EF是跟踪实体变化,然后将此变化映射到数据库的表中。EF上下文(DbContext)是与数据库的一次会话,我们要保证DbContext的线程唯一性。原因
如何保证EF上下文的唯一性呢?我们创建一个EFContextFactory工厂,让工厂中的GetCurrentDbContext()方法返回实例。
EFContextFactory
public partial class EFContextFactory { /// <summary> /// 帮我们返回当前线程内的数据库上下文,如果当前线程内没有上下文,那么创建一个上下文,并保证 /// 上下文是实例在线程内部唯一 /// 在EF4.0以前使用ObjectsContext对象 /// </summary> /// <returns></returns> public static DbContext GetCurrentDbContext() { //当第二次执行的时候直接取出线程嘈里面的对象 //CallContext:是线程内部唯一的独用的数据槽(一块内存空间) //数据存储在线程栈中 //线程内共享一个单例 DbContext dbcontext = CallContext.GetData("DbContext") as DbContext; //判断线程里面是否有数据 if (dbcontext == null) //线程的数据槽里面没有次上下文 { dbcontext = new DataModelContainer(); //创建了一个EF上下文 //存储指定对象 CallContext.SetData("DbContext", dbcontext); } return dbcontext; } }
BaseDAL修改为:
public partial class BaseDAL<T> where T : class { //EF上下文的实例保证,线程内唯一 //实例化EF框架 //DataModelContainer db = new DataModelContainer(); //修改部分 //获取的实当前线程内部的上下文实例,而且保证了线程内上下文实例唯一 private DbContext db = EFContextFactory.GetCurrentDbContext(); }
DbSession(之前的工厂RepositoryFactory):
public class DbSession //代表应用程序跟数据库之间的一次会话,也是数据库访问层的统一入口 { public IDAL.IRoleDAL RoleDAL { get { return new RoleDAL(); } } public IDAL.IUserInfoDAL UserInfoDAL { get { return new UserInfoDAL(); } } public int SaveChanges() //UintWork单元工作模式 { //调用EF上下文的SaveChanges的方法 return DAL.EFContextFactory.GetCurrentDbContext().SaveChanges(); } }
现在,我们实现了对于EF上下文的线程唯一性管理,那么为什么我们要在DbSession中调用EF上下文的SaveChanges方法呢?这里的SaveChanges方法相当于直接把当前线程内部所有实体的改变提交到数据库里面。当我们把BaseDAL中增删改方法中的SaveChanges方法删除掉时,我们的数据库访问层虽然调用了增删改的方法,但是没有真正的保存到数据库里面,这时,因为RepositoryFactory是数据层的统一入口,将SaveChanges全部给放到DbSession中去实现,DbSession我们就能够看成一个真正的会话了。也就是说我们在前面调用了很多次的增删改的实体之后(操作很多表),而只需要去DbSession中调用一个SaveChanges方法,就可以把所有的表实体的变化都放到数据库中去。
D层与EF上下文的关系
BaseService修改:
public abstract class BaseService<T> where T : class,new() { //在调用这个方法的时候必须给他赋值 public IDAL.IBaseRepository<T> CurrentRepository { get; set; } //DbSession的存放 public DbSession _DbSession = new DbSession(); //基类的构造函数 public BaseService() { SetCurrentRepository(); //构造函数里面调用了此设置当前仓储的抽象方法 } //构造方法实现赋值 public abstract void SetCurrentRepository(); //约束子类必须实现这个抽象方法 }
所以DbSession兼顾了简单工厂模式和SaveChange方法。然后因为DbSession就是我们整个数据库访问层的入口,那么我们DbSession也必须由一个接口的约束,那么我们在数据库访问接口层(LYZJ.UserLimitMVC.IDAL类库)加个接口约束,新建接口IDbSession。
业务逻辑层DbSession线程内唯一
(1)通过前面的博客我们知道我们将数据库访问层的BaseDAL(仓储)使用简单工厂来实现了线程内唯一的定义,代码如下:
//获取的实当前线程内部的上下文实例,而且保证了线程内上下文实例唯一 private DbContext db = EFContextFactory.GetCurrentDbContext();
(2)按照上面的说法的话,那么我们的业务逻辑层来获取DbSession的时候也是使用简单工厂来实现线程内唯一,那么我们修改DbSession的定义如下:
public abstract class BaseService<T> where T : class,new() { //DbSession的存放 public IDbSession _dbSession = DbSessionFactory.GetCurrentDbSession(); }
最后看一下DbSessionFactory的代码:
public class DbSessionFactory { /// <summary> /// 保证了线程内DbSession实例唯一 /// </summary> /// <returns></returns> public static IDbSession GetCurrentDbSession() { IDbSession _dbSession = CallContext.GetData("DbSession") as IDbSession; if (_dbSession == null) { _dbSession = new DbSession(); CallContext.SetData("DbSession", _dbSession); } return _dbSession; }
相关文章推荐
- android input子系统之二:核心层
- JavaScript isNaN() 函数
- 【HDU】 2818 Building Block
- c++11学习笔记3——通过更通用的方法实现新特性
- Tomcat6 一些调优设置内存和连接数
- jQuery选择器上
- java开发微信公众号企业付款开发
- Apache HBase 2015年发展回顾与未来展望
- git实验之代码提交
- 关于SwipeRefreshLayout+viewpager左右不能滑动
- configure: error: Invalid Net-SNMP directory - unable to find net-snmp-config
- Ring 0 Inline Hook
- shader
- iOS中如何优化Cell中图片的下载性能
- 一Java设计模式——需要遵守的六个原则
- QT sleep
- Windows Server 2003开机自动登录
- 【scikit-learn】评估分类器性能的度量,像混淆矩阵、ROC、AUC等
- QPushButton设置成带下划线的效果
- 在suse下rpm包安装