mvc5 + ef6 + autofac搭建项目(repository+uow)(一)

直奔主题了,不那么啰嗦。

一下分三个步骤说明,分别为 dbContext,repository,uow三点

在说之前,先说下O# 因为最近发现还有人在问,其实很好理解,简要说下理解步骤(O#的整体框架和上面的截图类似->_->我就是仿照的o#搭建的好不好)

如果对respository+uow熟练的人 ,一下就能看懂

看图一,图中的Core.Data.Entity

 

说实话,我也偷懒了,以下是 IRepository和IUnitofWork的定义

IRepository:

/// <summary>
    ///     实现仓储模型的数据标准操作
    /// </summary>
    public interface IRepository<TEntity> : IDependency
    {
        #region 属性
        /// <summary>
        ///     获取  当前单元操作对象
        /// </summary>
        IUnitOfWork UnitOfWork { get; }
        /// <summary>
        ///     获取当前实体查询数据集,数据将使用不跟踪变化的方式来查询
        /// </summary>
        IQueryable<TEntity> Entites { get; }

        #endregion

        #region 方法
        /// <summary>
        /// 插入实体
        /// </summary>
        /// <param name="entity">实体对象</param>
        /// <returns>操作影响的行数</returns>
        int Insert(TEntity entity, bool save = true);

        /// <summary>
        /// 批量插入实体
        /// </summary>
        /// <param name="entities">实体对象集合</param>
        /// <returns>操作影响的行数</returns>
        int Insert(IEnumerable<TEntity> entities, bool save = true);

        /// <summary>
        /// 删除实体
        /// </summary>
        /// <param name="entity">实体对象</param>
        /// <returns>操作影响的行数</returns>
        int Delete(TEntity entity, bool save = true);

        /// <summary>
        /// 删除指定编号的实体
        /// </summary>
        /// <param name="key">实体主键</param>
        /// <returns>操作影响的行数</returns>
        int Delete(object key, bool save = true);

        /// <summary>
        /// 删除所有符合特定条件的实体
        /// </summary>
        /// <param name="predicate">查询条件谓语表达式</param>
        /// <returns>操作影响的行数</returns>
        int Delete(Expression<Func<TEntity, bool>> predicate, bool save = true);

        /// <summary>
        /// 批量删除实体
        /// </summary>
        /// <param name="entities">实体对象集合</param>
        /// <returns>操作影响的行数</returns>
        int Delete(IEnumerable<TEntity> entities, bool save = true);

        /// <summary>
        ///     更新指定主键的对象
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        int Update(object key, bool save = true);

        /// <summary>
        /// 更新实体对象
        /// </summary>
        /// <param name="entity">更新后的实体对象</param>
        /// <returns>操作影响的行数</returns>
        int Update(TEntity entity, bool save = true);
        /// <summary>
        ///     批量更新数据
        /// </summary>
        /// <param name="entites">对象集合</param>
        /// <returns></returns>
        int Update(IEnumerable<TEntity> entites, bool save = true);
        ///// <summary>
        ///// 检查实体是否存在
        ///// </summary>
        ///// <param name="predicate">查询条件谓语表达式</param>
        ///// <param name="id">编辑的实体标识</param>
        ///// <returns>是否存在</returns>
        //bool CheckExists(Expression<Func<TEntity, bool>> predicate, object id);

        /// <summary>
        /// 查找指定主键的实体
        /// </summary>
        /// <param name="key">实体主键</param>
        /// <returns>符合主键的实体,不存在时返回null</returns>
        TEntity GetByKey(object key);

        /// <summary>
        /// 查询指定条件的实体
        /// </summary>
        /// <param name="predicate">查询表达式</param>
        /// <returns>符合条件的实体集合</returns>
        IEnumerable<TEntity> GetByPredicate(Expression<Func<TEntity, bool>> predicate);

        /// <summary>
        /// 获取贪婪加载导航属性的查询数据集
        /// </summary>
        /// <param name="path">属性表达式,表示要贪婪加载的导航属性</param>
        /// <returns>查询数据集</returns>
        IQueryable<TEntity> GetInclude<TProperty>(Expression<Func<TEntity, TProperty>> path);

        /// <summary>
        /// 获取贪婪加载多个导航属性的查询数据集
        /// </summary>
        /// <param name="paths">要贪婪加载的导航属性名称数组</param>
        /// <returns>查询数据集</returns>
        IQueryable<TEntity> GetIncludes(params string[] paths);

        /// <summary>
        /// 创建一个原始 SQL 查询,该查询将返回此集中的实体。 
        /// 默认情况下,上下文会跟踪返回的实体;可通过对返回的 DbRawSqlQuery 调用 AsNoTracking 来更改此设置。 请注意返回实体的类型始终是此集的类型,而不会是派生的类型。 如果查询的一个或多个表可能包含其他实体类型的数据,则必须编写适当的 SQL 查询以确保只返回适当类型的实体。 与接受 SQL 的任何 API 一样,对任何用户输入进行参数化以便避免 SQL 注入攻击是十分重要的。 您可以在 SQL 查询字符串中包含参数占位符,然后将参数值作为附加参数提供。 您提供的任何参数值都将自动转换为 DbParameter。 context.Set(typeof(Blog)).SqlQuery("SELECT * FROM dbo.Posts WHERE Author = @p0", userSuppliedAuthor); 或者,您还可以构造一个 DbParameter 并将它提供给 SqlQuery。 这允许您在 SQL 查询字符串中使用命名参数。 context.Set(typeof(Blog)).SqlQuery("SELECT * FROM dbo.Posts WHERE Author = @author", new SqlParameter("@author", userSuppliedAuthor));
        /// </summary>
        /// <param name="trackEnabled">是否跟踪返回实体</param>
        /// <param name="sql">SQL 查询字符串。</param>
        /// <param name="parameters">要应用于 SQL 查询字符串的参数。 如果使用输出参数,则它们的值在完全读取结果之前不可用。 这是由于 DbDataReader 的基础行为而导致的,有关详细信息,请参见 http://go.microsoft.com/fwlink/?LinkID=398589</param>
        /// <returns></returns>
        IEnumerable<TEntity> SqlQuery(string sql, bool trackEnabled = true, params object[] parameters);

        /// <summary>
        ///     分页数据查询
        /// </summary>
        /// <param name="pageCondition">分页和排序条件</param>
        /// <param name="predicate">数据过滤条件 表达式</param>
        /// <returns>分页后的数据集合</returns>
        IQueryable<TEntity> Get(PageCondition pageCondition, Expression<Func<TEntity, bool>> predicate, out int totalRow);

        #endregion

    }

IUnitOfWork:

/// <summary>
    ///     
    /// </summary>
    public interface IUnitOfWork: IDependency, IDisposable
    {

        #region 方法
        /// <summary>
        ///     命令提交
        /// </summary>
        /// <returns>提交操作结果</returns>
        int SaveChanges(bool save);


        DbContext DbContext { get; }
        #endregion


    }

此处之所以这么定义(只有两个对象),看上一篇关于 repository和uow的关系

对应的repository和uow的实现
repository:

/// <summary>
    ///     仓储
    /// </summary>
    public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
    {
        #region Fields
        private readonly IUnitOfWork _unitOfWork;
        private readonly DbSet<TEntity> _dbSet;
        #endregion

        #region ctor
        /// <summary>
        /// 初始化一个<see cref="Repository{TEntity}"/>类型的新实例
        /// </summary>
        public Repository(IUnitOfWork unitOfWork)
        {
            this._unitOfWork = unitOfWork;
            this._dbSet = _unitOfWork.DbContext.Set<TEntity>();
        }
        #endregion

        #region 属性
        /// <summary>
        /// 获取 当前实体类型的查询数据集,数据将使用不跟踪变化的方式来查询
        /// </summary>
        public IQueryable<TEntity> Entites { get { return _dbSet.AsNoTracking(); } }
        /// <summary>
        /// 获取 当前单元操作对象
        /// </summary>
        public IUnitOfWork UnitOfWork { get { return _unitOfWork; } }

        #endregion

        #region 方法

        ///// <summary>
        /////     判断指定表达式条件 的对象是否存在
        ///// </summary>
        ///// <param name="predicate"></param>
        ///// <param name="id"></param>
        ///// <returns></returns>
        //public bool CheckExists(Expression<Func<TEntity, bool>> predicate, object id)
        //{
        //    var entity = _dbSet.Where(predicate).Select(m => )
        //}
        /// <summary>
        /// 删除所有符合特定条件的实体
        /// </summary>
        /// <param name="predicate">查询条件谓语表达式</param>
        /// <returns>操作影响的行数</returns>
        public int Delete(Expression<Func<TEntity, bool>> predicate, bool save = true)
        {
            var entities = _dbSet.Where(predicate).AsEnumerable();
            if (null != entities && entities.Count() > 0)
            {
                _dbSet.RemoveRange(entities);
            }
            return _unitOfWork.SaveChanges(save);
        }
        /// <summary>
        /// 批量删除实体
        /// </summary>
        /// <param name="entities">实体对象集合</param>
        /// <returns>操作影响的行数</returns>
        public int Delete(IEnumerable<TEntity> entities, bool save = true)
        {
            if (null != entities && entities.Count() > 0)
            {
                _dbSet.RemoveRange(entities);
            }
            return _unitOfWork.SaveChanges(save);
        }

        public int Delete(object key, bool save = true)
        {
            var entity = _dbSet.Find(key);
            _dbSet.Remove(entity);
            return _unitOfWork.SaveChanges(save);
        }

        public int Delete(TEntity entity, bool save = true)
        {
            _dbSet.Remove(entity);
            return _unitOfWork.SaveChanges(save);
        }

        public TEntity GetByKey(object key)
        {
            return _dbSet.Find(key);
        }

        public IEnumerable<TEntity> GetByPredicate(Expression<Func<TEntity, bool>> predicate)
        {
            return _dbSet.Where(predicate).AsEnumerable();
        }

        public IQueryable<TEntity> GetInclude<TProperty>(Expression<Func<TEntity, TProperty>> path)
        {
            return _dbSet.Include(path);
        }

        public IQueryable<TEntity> GetIncludes(params string[] paths)
        {
            IQueryable<TEntity> sources = null;
            foreach (var path in paths)
            {
                sources = _dbSet.Include(path);
            }
            return sources;
        }

        public int Insert(IEnumerable<TEntity> entities, bool save = true)
        {
            _dbSet.AddRange(entities);
            return _unitOfWork.SaveChanges(save);
        }

        public int Insert(TEntity entity, bool save = true)
        {
            _dbSet.Add(entity);
            return _unitOfWork.SaveChanges(save);
        }

        public IEnumerable<TEntity> SqlQuery(string sql, bool trackEnabled = true, params object[] parameters)
        {
            return trackEnabled
                 ? _dbSet.SqlQuery(sql, parameters)
                 : _dbSet.SqlQuery(sql, parameters).AsNoTracking();
        }

        public int Update(object key, bool save = true)
        {
            var entity = _dbSet.Find(key);
            return Update(entity, save);
        }

        public int Update(TEntity entity, bool save = true)
        {
            DbContext context = ((DbContext)_unitOfWork);

            DbSet<TEntity> dbSet = context.Set<TEntity>();
            try
            {
                DbEntityEntry<TEntity> entry = context.Entry(entity);
                if (entry.State == EntityState.Detached)
                {
                    dbSet.Attach(entity);
                    entry.State = EntityState.Modified;
                }
            }
            catch (InvalidOperationException ex)
            {
                throw new Exception(ex.Message);
            }
            return _unitOfWork.SaveChanges(save);
        }

        public int Update(IEnumerable<TEntity> entites, bool save = true)
        {
            DbContext context = ((DbContext)_unitOfWork);

            DbSet<TEntity> dbSet = context.Set<TEntity>();

            foreach (var entity in entites)
            {
                try
                {
                    DbEntityEntry<TEntity> entry = context.Entry(entity);
                    if (entry.State == EntityState.Detached)
                    {
                        dbSet.Attach(entity);
                        entry.State = EntityState.Modified;
                    }
                }
                catch (InvalidOperationException ex)
                {
                    throw new Exception(ex.Message);
                }
            }

            return _unitOfWork.SaveChanges(save);
        }


        public IQueryable<TEntity> Get(PageCondition pageCondition, Expression<Func<TEntity, bool>> predicate, out int totalRow)
        {
            int totalCount = 0;
            IQueryable<TEntity> source = _dbSet.Where(predicate);
            if (pageCondition.SortConditions == null || pageCondition.SortConditions.Length == 0)
            {
                source = source.OrderBy("Id");
            }
            else
            {
                int count = 0;
                IOrderedQueryable<TEntity> orderSource = null;
                foreach (SortCondition sortCondition in pageCondition.SortConditions)
                {
                    orderSource = count == 0
                        ? CollectionPropertySorter<TEntity>.OrderBy(source, sortCondition.SortField, sortCondition.ListSortDirection)
                        : CollectionPropertySorter<TEntity>.ThenBy(orderSource, sortCondition.SortField, sortCondition.ListSortDirection);
                    count++;
                }
                source = orderSource;
                totalCount = source.Count();
            }
            int pageIndex = pageCondition.PageIndex, pageSize = pageCondition.PageSize;
            source = source != null
                ? source.Skip((pageIndex - 1) * pageSize).Take(pageSize)
                : Enumerable.Empty<TEntity>().AsQueryable();
            //IQueryable<TResult> query = source.Select(selector);
            //return GetKey(query.Expression);
            totalRow = totalCount;
            return source;
        }




        #endregion

    }

uow:

/// <summary>
    ///     工作单元实现
    /// </summary>
    public class UnitOfWork :  IUnitOfWork
    {
        private bool _disposed;
        private DbContext _dbContext;

        public UnitOfWork()
        {
            this._dbContext = DbContext;
        }

        /// <summary>
        ///     数据提交操作
        /// </summary>
        /// <returns></returns>
        public int SaveChanges(bool save)
        {
            if (save)
            {
                try
                {
                    try
                    {
                        return _dbContext.SaveChanges();
                    }
                    catch (DbEntityValidationException dbex)
                    {

                        throw;
                    }
                }
                catch (Exception ex)
                {

                    throw;
                }
            }
            return 0;
        }

        public  DbContext DbContext
        {
            get
            {
                //CallContext:是线程内部唯一的独用的数据槽(一块内存空间)
                //传递DbContext进去获取实例的信息,在这里进行强制转换。
                DbContext dbContext = CallContext.GetData("DbContext") as DbContext;
                if (dbContext == null)  //线程在数据槽里面没有此上下文
                {
                    dbContext = new InnovatorContext(); //如果不存在上下文的话,创建一个EF上下文
                                                        //我们在创建一个,放到数据槽中去
                    CallContext.SetData("DbContext", dbContext);
                }
                return dbContext;
            }
        }

        public virtual void Dispose(bool disposing)
        {
            if (!this._disposed)
                if (disposing)
                    this._dbContext.Dispose();

            this._disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
        }
    }

脚本中涉及到的 SortDirection源自O#的干货中的实现,具体参见 o#

至此,该内容已完毕,以上实现院子处处有,再说闲的多余了。

 

转载于:https://www.cnblogs.com/Tmc-Blog/p/5061414.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
大体分为3个阶段的学习: 第一阶段是mvc基础的学习,通过通俗易懂的例子,体现mvc框架的优势; 第二阶段是EF的学习,通过实际案例,体现orm框架的伟大之处; 第三阶段是项目开发阶段,采用mvc+ef+多层架构的布局,采用TDD的开发模式,大概的功能如下: &nbsp; &nbsp;《巧租房》是一个手机版的租房网站,提供了搜索房源、预约看房、房源委托、后台抢单、房源管理、操作日志、定时报表、配置管理等功能。项目采用的是b/s模式的架构,包括一个后台管理和一个前端的可以自适应于手机端的页面,项目全程采用TDD开发模式,用到如下的技术:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;前端技术:前端MVC引擎(artTemplate)、HUI、MUI(手机端自适应)、ValidForm、Layer; &nbsp; &nbsp; .Net高级技术:自定义Filter、自定义ModelBinder、ASP.Net MVC+EntityFramework实践; &nbsp; &nbsp; &nbsp;大型网站架构:UnitTest、AutoFac、分布式架构(Redis、Memecached等)、CDN与云存储、云计算服务(短信验证、SendCloud邮件云)、RBAC权限控制、页面静态化和SSI;数据库并发控制(悲观锁与乐观锁); &nbsp; &nbsp; &nbsp; 高级开源组件:ElasticSearch全文搜索引擎;Quartz.Net定时调度;UEditor;Log4Net**版;互联网网站安全(XSS、CSRF等);CodeCarvings.Piczard(水印、缩略图);CaptchaGen(验证码);WebUploader文件无刷新上传
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值