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

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

  • 相关阅读:
    从句分析
    artDialog ( v 6.0.2 ) content 参数引入页面 html 内容
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 11 盛最多水的容器
    Java实现 LeetCode 11 盛最多水的容器
  • 原文地址:https://www.cnblogs.com/Tmc-Blog/p/5061414.html
Copyright © 2011-2022 走看看