MVC+Ef项目(3) 抽象数据库访问层的统一入口;EF上下文线程内唯一
抽象一个数据库访问层的统一入口(类似于EF的上下文,拿到上下文,就可以拿到所有的表).实际这个入口就是一个类,类里面有所有的仓储对应的属性.这样,只要拿到这个类的实例,就可以点出所有的仓储,我们在 Repository层里面添加一个类 DbSession.cs
namespace YouJiao.MvcWeb.Repository { /// <summary> /// 相当于是简单工厂:通过DbSession可以拿到所有的仓储的实例,所以我们也可以将此DbSession看做是简单工厂. /// 职责:对整个数据库访问层做了高度抽象,它是整个数据库访问层的统一入口,BLL层来调用Repository层的时候 /// 只要拿到DbSession就可以拿到所有的仓储,就可以对所有的表进行增删改查了 /// </summary> public class DbSession : IDbSession { public ObjectContext db = new ModelContainer(); //EF上下文 我们先直接new 后面再来修改成线程内唯一 private IUserInfoRepository _userInfoRepository; public IUserInfoRepository UserInfoRepository { get { if (_userInfoRepository == null) { _userInfoRepository = new UserInfoRepository(); } return _userInfoRepository; } set { _userInfoRepository = value; } } private IProductRepository _productRepository; public IProductRepository ProductRepository { get { if (_productRepository == null) { _productRepository = new ProductRepository(); } return _productRepository; } set { _productRepository = value; } } //执行sql脚本 public int ExecuteSql(string sql, ObjectParameter[] parameters) { return db.ExecuteFunction(sql, parameters); } //单元工作模式 public int SaveChanges() { return db.SaveChanges(); } } }
然后我们抽象出一个接口,在 IRepository里面增加一个 IDbSession.cs
namespace YouJiao.MvcWeb.IRepository { public interface IDbSession { IUserInfoRepository UserInfoRepository { get; set; } IProductRepository ProductRepository { get; set; } int ExecuteSql(string sql, ObjectParameter[] parameters); /// <summary> /// 将整个数据库访问层的所有修改都一次性的提交回数据库 /// 业务逻辑层:一个业务场景,肯定会对多个表做修改,对多个表进行处理 /// 此方法的存在:极大的提高数据库访问层批量提交sql的性能,提高数据库的吞吐量,减少跟数据库的交互次数 /// </summary> /// <returns></returns> int SaveChanges(); //UnitWork模式 } }
这样结构就变成了下图所示
然后我们再来修改一下 EF上下文的实例,在BaseRepository和DbSession里面都有用到 上下文,我们要保证这个上下文在线程内是唯一的
我们在 Repository层,创建一个EF的简单工厂 实际也就是一个类(DbEfContextFactory),里面一个静态方法(GetCurrentDbEfContext)
namespace YouJiao.MvcWeb.Repository { public class DbEfContextFactory { public static ObjectContext GetCurrentDbEfContext() { //CallContext:是线程内部唯一的独用的数据槽(一块内存空间) //传递dbcontext进去获取实例的信息,在这里进行强制转换。 ObjectContext context = (ObjectContext) CallContext.GetData("dbcontext"); if (context == null) //如果线程在数据槽里面没有此上下文 { context=new ModelContainer(); //那么我们自己就new一个 CallContext.SetData("dbcontext",context); //放到数据槽中 } return context; } } }
现在我们来修改一下刚才 DbSession.cs 和 BaseRepository.cs
namespace YouJiao.MvcWeb.Repository { /// <summary> /// 相当于是简单工厂:通过DbSession可以拿到所有的仓储的实例,所以我们也可以将此DbSession看做是简单工厂. /// 职责:对整个数据库访问层做了高度抽象,它是整个数据库访问层的统一入口,BLL层来调用Repository层的时候 /// 只要拿到DbSession就可以拿到所有的仓储,就可以对所有的表进行增删改查了 /// </summary> public class DbSession : IDbSession { public ObjectContext db { get { return DbEfContextFactory.GetCurrentDbEfContext();//EF上下文线程内唯一 } } private IUserInfoRepository _userInfoRepository; public IUserInfoRepository UserInfoRepository { get { if (_userInfoRepository == null) { _userInfoRepository = new UserInfoRepository(); } return _userInfoRepository; } set{_userInfoRepository = value;} } private IProductRepository _productRepository; public IProductRepository ProductRepository { get { if (_productRepository == null) { _productRepository = new ProductRepository(); } return _productRepository; } set { _productRepository = value; } } //执行sql脚本 public int ExecuteSql(string sql, ObjectParameter[] parameters) { return db.ExecuteFunction(sql, parameters); } //单元工作模式 public int SaveChanges() { return db.SaveChanges(); } } }
namespace YouJiao.MvcWeb.Repository { public class BaseRepository<T> where T : class // 这里约束泛型T必须是个类 { private ObjectContext db { get { return DbEfContextFactory.GetCurrentDbEfContext();//获取EF上下文的实例 } } public IList<T> LoadEneities(Func<T, bool> whereLambda) { return db.CreateObjectSet<T>().Where(whereLambda).ToList(); } public IList<T> LoadPageEneities<S>(int pageSize, int pageIndex, out int total, Func<T, bool> whereLambda, Func<T, S> orderbyLambda, bool isAsc) { var tempList = db.CreateObjectSet<T>().Where(whereLambda).ToList(); total = tempList.Count; if (isAsc) //如果是升序 { tempList = tempList.OrderBy(orderbyLambda) .Skip(pageIndex * pageSize - 1) //越过多少条 .Take(pageSize).ToList(); //取出多少条 } else { tempList = tempList.OrderByDescending(orderbyLambda) .Skip(pageIndex * pageSize - 1) .Take(pageSize).ToList(); } return tempList; } public T AddEntity(T model) { db.CreateObjectSet<T>().AddObject(model); db.SaveChanges(); return model; } public bool DeleteEntity(T model) { db.CreateObjectSet<T>().Attach(model); db.ObjectStateManager.ChangeObjectState(model, EntityState.Deleted); return db.SaveChanges() > 0; } public bool UpdateEntity(T model) { db.CreateObjectSet<T>().Attach(model); db.ObjectStateManager.ChangeObjectState(model, EntityState.Modified); return db.SaveChanges() > 0; } } }