• 说说IUnitOfWork~我的IUnitOfWork+Repository架构


    回到目录

    第一讲 认识IUnitOfWork,为什么要出现IUnitOfWork接口
    第二讲 Linq to Sql与EntityFrameworks中的SubmtChanges()发生了什么事
    第三讲 方法完整性与统一提交不冲突
    第四讲 DbContext对象的创建应该向BLL层公开
    第五讲 我的IUnitOfWork+Repository架构

    这个系统的文章在写完这篇后将拉下眉目,一共5讲的IUnitOfWork带给我们的是性能,原子化操作,等多方法的改进,下面我把我的IUnitOfWork+Repository模式大体的说一下,并代上核心代码:

    底层接口UnitOfWork.Data.Core

    这是一个接口规范的项目层,它由CURD操作规范和UnitOfWork规范组成

    namespace UnitOfWork.Data.Core
    {
        /// <summary>
        /// 工作单元
        /// 提供一个保存方法,它可以对调用层公开,为了减少连库次数
        /// </summary>
        public interface IUnitOfWork
        {
            /// <summary>
            /// 将操作提交到数据库,
            /// </summary>
            void Save();
            /// <summary>
            /// 是否不提交到数据库,这只是在具体的repository类中的SaveChanges方法里用到的
            /// 默认为false,即默认为提交到数据库
            /// </summary>
            /// <returns></returns>
            bool IsNotSubmit { get; set; }
        }
    
        /// <summary>
        /// 工作单元
        /// 对泛型类型的支持
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public interface IUnitOfWork<T> : IUnitOfWork where T : class { }
    
    }
    namespace UnitOfWork.Data.Core
    {
        public interface IRepository<TEntity>
               where TEntity : class
        {
            /// <summary>
            /// 添加实体并提交到数据服务器
            /// </summary>
            /// <param name="item">Item to add to repository</param>
            void Insert(TEntity item);
    
            /// <summary>
            /// 移除实体并提交到数据服务器
            /// 如果表存在约束,需要先删除子表信息
            /// </summary>
            /// <param name="item">Item to delete</param>
            void Delete(TEntity item);
    
            /// <summary>
            /// 修改实体并提交到数据服务器
            /// </summary>
            /// <param name="item"></param>
            void Update(TEntity item);
    
            /// <summary>
            /// Get all elements of type {T} in repository
            /// </summary>
            /// <returns>List of selected elements</returns>
            IQueryable<TEntity> GetModel();
    
            /// <summary>
            /// 根据主键得到实体
            /// </summary>
            /// <param name="id"></param>
            /// <returns></returns>
            TEntity Find(params object[] id);
        }
    }
    namespace UnitOfWork.Data.Core
    {
        /// <summary>
        /// 扩展的Repository操作规范
        /// </summary>
        public interface IExtensionRepository<TEntity> where TEntity : class
        {
            /// <summary>
            /// 添加集合
            /// </summary>
            /// <param name="item"></param>
            void Insert(IEnumerable<TEntity> item);
    
            /// <summary>
            /// 修改集合
            /// </summary>
            /// <param name="item"></param>
            void Update(IEnumerable<TEntity> item);
    
            /// <summary>
            /// 删除集合
            /// </summary>
            /// <param name="item"></param>
            void Delete(IEnumerable<TEntity> item);
    
            /// <summary>
            /// 扩展更新方法,只对EF支持
            /// </summary>
            /// <param name="entity"></param>
            void Update(System.Linq.Expressions.Expression<Action<TEntity>> entity);
        }
    }
    namespace UnitOfWork.Data.Core
    {
        /// <summary>
        /// 完整的数据操作接口
        /// </summary>
        public interface ICompleteRepository<T> :
            IRepository<T>,
            IExtensionRepository<T>
             where T : class
        {
        }
    }

    而在DATA层需要去实现这些接口,我们以EF为例,去实现这样接口:

    namespace EntityFrameworks.Data.Core
    {
        using UnitOfWork.Data.Core;
        using System.Data.Entity.Infrastructure;
    
        public class DbContextRepository<TEntity> :
            ICompleteRepository<TEntity> where TEntity : class
        {
            protected DbContext _db { get; private set; }
            IUnitOfWork iUnitWork;
            public DbContextRepository(IUnitOfWork db)
            {
                iUnitWork = db;
                _db = (DbContext)db;
            }
    
            #region IRepository<T> 成员
    
            public virtual void Insert(TEntity item)
            {
                _db.Entry<TEntity>(item);
                _db.Set<TEntity>().Add(item);
                this.SaveChanges();
            }
    
            public virtual void Delete(TEntity item)
            {
                _db.Set<TEntity>().Attach(item);
                _db.Set<TEntity>().Remove(item);
                this.SaveChanges();
            }
    
            public virtual void Update(TEntity item)
            {
                _db.Set<TEntity>().Attach(item);
                _db.Entry(item).State = EntityState.Modified;
                this.SaveChanges();
            }
    
            public void Update(Expression<Action<TEntity>> entity)
            {
    
                TEntity newEntity = typeof(TEntity).GetConstructor(Type.EmptyTypes).Invoke(null) as TEntity;//建立指定类型的实例
                List<string> propertyNameList = new List<string>();
                MemberInitExpression param = entity.Body as MemberInitExpression;
                foreach (var item in param.Bindings)
                {
                    string propertyName = item.Member.Name;
                    object propertyValue;
                    var memberAssignment = item as MemberAssignment;
                    if (memberAssignment.Expression.NodeType == ExpressionType.Constant)
                    {
                        propertyValue = (memberAssignment.Expression as ConstantExpression).Value;
                    }
                    else
                    {
                        propertyValue = Expression.Lambda(memberAssignment.Expression, null).Compile().DynamicInvoke();
                    }
                    typeof(TEntity).GetProperty(propertyName).SetValue(newEntity, propertyValue, null);
                    propertyNameList.Add(propertyName);
                }
                _db.Set<TEntity>().Attach(newEntity);
                _db.Configuration.ValidateOnSaveEnabled = false;
                var ObjectStateEntry = ((IObjectContextAdapter)_db).ObjectContext.ObjectStateManager.GetObjectStateEntry(newEntity);
                propertyNameList.ForEach(x => ObjectStateEntry.SetModifiedProperty(x.Trim()));
                this.SaveChanges();
                //  ((IObjectContextAdapter)_db).ObjectContext.Detach(newEntity);
            }
    
            public IQueryable<TEntity> GetModel()
            {
                //  return _db.Set<TEntity>().AsNoTracking();
                return _db.Set<TEntity>();
            }
    
            #endregion
    
            #region IExtensionRepository<T> 成员
    
            public virtual void Insert(IEnumerable<TEntity> item)
            {
                item.ToList().ForEach(i =>
                {
                    this.Insert(i);//不提交
                });
            }
    
            public virtual void Delete(IEnumerable<TEntity> item)
            {
                item.ToList().ForEach(i =>
                {
                    this.Delete(i);
                });
            }
    
            public virtual void Update(IEnumerable<TEntity> item)
            {
                item.ToList().ForEach(i =>
                {
                    this.Update(i);
                });
            }
    
            public TEntity Find(params object[] id)
            {
                return _db.Set<TEntity>().Find(id);
            }
    
            #endregion
    
            #region Protected Methods
            /// <summary>
            /// 根据工作单元的IsNotSubmit的属性,去判断是否提交到数据库
            /// 一般地,在多个repository类型进行组合时,这个IsNotSubmit都会设为true,即不马上提交,
            /// 而对于单个repository操作来说,它的值不需要设置,使用默认的false,将直接提交到数据库,这也保证了操作的原子性。
            /// </summary>
            protected void SaveChanges()
            {
                if (!iUnitWork.IsNotSubmit)
                    iUnitWork.Save();
            }
    
            /// <summary>
            ///  计数更新,与SaveChange()是两个SQL链接,走分布式事务
            ///  子类可以根据自己的逻辑,去复写
            ///  tableName:表名
            ///  param:索引0为主键名,1表主键值,2为要计数的字段,3为增量
            /// </summary>
            /// <param name="tableName">表名</param>
            /// <param name="param">参数列表,索引0为主键名,1表主键值,2为要计数的字段,3为增量</param>
            protected virtual void UpdateForCount(string tableName, params object[] param)
            {
                string sql = "update [" + tableName + "] set [{2}]=ISNULL([{2}],0)+{3} where [{0}]={1}";
                List<object> listParasm = new List<object>
                {
                    param[0],
                    param[1],
                    param[2],
                    param[3],
                };
                _db.Database.ExecuteSqlCommand(string.Format(sql, listParasm.ToArray()));
            }
            #endregion
    
        }
    }

    在Entity实体模型层,需要去继承IUnitOfWork这个接口,并去实现它:

     public partial class backgroundEntities : IUnitOfWork
        {
            #region IUnitOfWork 成员
    
            public void Save()
            {
                this.SaveChanges();
            }
    
            public bool IsNotSubmit
            {
                get;
                set;
            }
    
            #endregion
    
        }

    最后在BLL层来完成业务的组成及基础操作的实现

    namespace BLL
    {
        public abstract class BLLBase
        {
            protected IUnitOfWork IUnitOfWork { get; private set; }
            public BLLBase()
                : this(null)
            {
    
            }
            public BLLBase(IUnitOfWork iUnitOfWork)
            {
                IUnitOfWork = iUnitOfWork;
            }
            protected ICompleteRepository<T> LoadRepository<T>() where T : class
            {
                return IUnitOfWork == null ? new TestBase<T>() : new TestBase<T>(IUnitOfWork);
            }
        }
    }

    在BLL层具体业务实现中,去继承BLLBase,并将数据上下文以参数的形式传递过去:

     public class OrderManager : BLLBase
        {
            public OrderManager()
                : base(new TestDataContext())
            {
    
            }
            public void GeneratorOrder(Order_Info order)
            {
                GeneratorOrder(order, null);
            }
            public void GeneratorOrder(Order_Info order, Product product)
            {
    
                #region BLLBase中直接调用公用方法
                IUnitOfWork.IsNotSubmit = true;
                new OrderRepository(IUnitOfWork).Insert(order);//DAL层具体的Repository实现类
                if (product != null)
                    LoadRepository<Product>().Insert(product);//BLLBase提供的单纯CURD操作
                IUnitOfWork.SaveChanges();
                #endregion
            }
    }

    在WEB层直接调用BLL的具体业务即可!

    到此,我们的UnitOfWork系列就讲完了,各位,晚安了!

     回到目录

  • 相关阅读:
    Codeforces Round #370 (Div. 2) C. Memory and De-Evolution 水题
    Codeforces Round #370 (Div. 2) B. Memory and Trident 水题
    Codeforces Round #370 (Div. 2) A. Memory and Crow 水题
    Codeforces Round #258 (Div. 2) E. Devu and Flowers 容斥
    Codeforces Round #258 (Div. 2) D. Count Good Substrings 水题
    Codeforces Round #258 (Div. 2) C. Predict Outcome of the Game 水题
    Codeforces Round #258 (Div. 2) . Sort the Array 贪心
    Codeforces Round #258 (Div. 2) A. Game With Sticks 水题
    Codeforces Beta Round #14 (Div. 2) D. Two Paths 树形dp
    Codeforces Beta Round #14 (Div. 2) C. Four Segments 水题
  • 原文地址:https://www.cnblogs.com/lori/p/2974540.html
Copyright © 2020-2023  润新知