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;
            }
        }
    }
  • 相关阅读:
    QFramework 使用指南 2020(二):下载与版本介绍
    QFramework 使用指南 2020 (一): 概述
    Unity 游戏框架搭建 2018 (二) 单例的模板与最佳实践
    Unity 游戏框架搭建 2018 (一) 架构、框架与 QFramework 简介
    Unity 游戏框架搭建 2017 (二十三) 重构小工具 Platform
    Unity 游戏框架搭建 2017 (二十二) 简易引用计数器
    Unity 游戏框架搭建 2017 (二十一) 使用对象池时的一些细节
    你确定你会写 Dockerfile 吗?
    小白学 Python 爬虫(8):网页基础
    老司机大型车祸现场
  • 原文地址:https://www.cnblogs.com/joeylee/p/3626199.html
Copyright © 2011-2022 走看看