zoukankan      html  css  js  c++  java
  • 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模式
        }
    }

    这样结构就变成了下图所示

    image

    然后我们再来修改一下 EF上下文的实例,在BaseRepository和DbSession里面都有用到 上下文,我们要保证这个上下文在线程内是唯一的

    image

    image

    我们在 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;
            }
        }
    }
  • 相关阅读:
    产品经理职责
    Python基础知识之:字符串拼接
    Python基础知识之:hello world,注释,变量,数据类型
    Python初接触
    系统测试基础大纲
    编程零基础应当如何开始学习 Python?
    可以用 Python 编程语言做哪些神奇好玩的事情?
    江湖二三事:听说你想做数据分析师?
    “羊车门”问题
    用Turtle画正螺旋线
  • 原文地址:https://www.cnblogs.com/joeylee/p/3626199.html
Copyright © 2011-2022 走看看