LCLFramework框架之Repository模式

本文介绍了Repository模式的实际应用价值,包括封装数据查询与存储逻辑、更换ORM引擎不影响业务逻辑、提高单元测试效率等。同时探讨了Repository与Dal的区别,并通过LCLFramework框架展示了Repository模式的设计与实现。
摘要由CSDN通过智能技术生成

Respository模式在示例中的实际目的小结一下


  1. Repository模式是架构模式,在设计架构时,才有参考价值;
  2. Repository模式主要是封装数据查询和存储逻辑;
  3. Repository模式实际用途:更换、升级ORM 引擎,不影响业务逻辑;
  4. Repository模式能提高测试效率,单元测试时,用Mock对象代替实际的数据库存取,可以成倍地提高测试用例运行速度。

Repository与Dal的区别


     Repository是DDD中的概念,强调Repository是受Domain驱动的,Repository中定义的功能要体现Domain的意图和约束,而Dal更纯粹的就是提  供数据访问的功能,并不严格受限于Business层。

     使用Repository,隐含着一种意图倾向,就是 Domain需要什么我才提供什么,不该提供的功能就不要提供,一切都是以Domain的需求为核心;而使用Dal,其意图倾向在于我Dal层能使用的数 据库访问操作提供给Business层,你Business要用哪个自己选。换一个Business也可以用我这个Dal,一切是以我Dal能提供什么操 作为核心。

LCLFramework框架之Repository模式设计


     LCLFramework框架之Repository模式设计主要是参考http://apworks.codeplex.com/ 框架而来的,目前我只是扩展了LCL.Repositories.EntityFramework仓库,对于个人来使用已经足够了。

ard_thumb[1]

LCLFramework框架之Repository模式设计代码


clipboard[1] 

复制代码
public interface IRepository<TEntity> where TEntity : class, IEntity
  {
      IRepositoryContext Context { get; }
      void Create(TEntity entity);
      void Delete(TEntity entity);
      void Update(TEntity entity);
      IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> predicate);
      IEnumerable<TEntity> GetAll(PagingInfo paging = null);
      TEntity GetByKey(params object[] keyValues);
      IEnumerable<TEntity> GetPage(Expression<Func<TEntity, bool>> predicate,PagingInfo paging);
  }
public interface IRepositoryContext : IUnitOfWork, IDisposable
{
    Guid ID { get; }
    void RegisterNew(object obj);
    void RegisterModified(object obj);
    void RegisterDeleted(object obj);
} 

public interface IUnitOfWork
{
    bool DistributedTransactionSupported { get; }
    bool Committed { get; }
    void Commit();
    void Rollback();
}
/* 

职责: 

   1:定义一个“仓库”基类 

   2:与WCF交互,Repository<TEntity>类的红色部分是与WCF交互的代码。通过“数据门户”来决定是本地执行还是网络执行。 

*/ 

public abstract partial class Repository<TEntity> : IRepository<TEntity>
    where TEntity : class, IEntity
{
    /// <summary>
    /// 是否声明本仓库为本地仓库(客户端只在客户端查询,服务端在服务端查询)
    /// </summary>
public DataPortalLocation DataPortalLocation { get; protected set; } 

    private readonly IRepositoryContext context;
    public Repository(IRepositoryContext context)
    {
        this.context = context;
this.DataPortalLocation = DataPortalLocation.Dynamic;
    }
    public IRepositoryContext Context
    {
        get { return this.context; }
    }
    #region IRepositoryContext
    #region CUD
    protected abstract void DoAdd(TEntity entity);
    protected abstract void DoRemove(TEntity entity);
    protected abstract void DoUpdate(TEntity entity);
    [Obfuscation]
    public void Create(TEntity entity)
    {
   this.FetchList(entity, "DoAdd");
    }
    public void Delete(TEntity entity)
    {
this.FetchList(entity, "DoRemove");
    }
    public void Update(TEntity entity)
    {
this.FetchList(entity, "DoUpdate");
    }
    #endregion 

    #region Query
    protected abstract IEnumerable<TEntity> DoGetAll(PagingInfo paging);
    protected abstract IEnumerable<TEntity> DoGet(Expression<Func<TEntity, bool>> predicate);
    protected abstract TEntity DoGetByKey(params object[] keyValues);
    protected abstract IEnumerable<TEntity> DoGetPage(Expression<Func<TEntity, bool>> predicate, PagingInfo paging);
    public IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> predicate)
    {
var list = this.FetchList(predicate, "DoGet");
        return list;
    }
    public IEnumerable<TEntity> GetAll(PagingInfo paging=null)
    {
  var list = this.FetchList(paging, "DoGetAll");
        return list;
    }
    public TEntity GetByKey(params object[] keyValues)
    {
var list = this.FetchFirst(keyValues, "GetByKey");
        return list;
    }
    public IEnumerable<TEntity> GetPage(Expression<Func<TEntity, bool>> predicate,PagingInfo paging=null)
    {
return this.FetchList(paging, "GetPage");
    }
    #endregion
    #endregion 

       #region 获取对象接口方法 

        protected TEntityList FetchListCast<TEntityList>(object criteria, string methodName) 

            where TEntityList : class, IEnumerable<TEntity> 

        { 

            return this.FetchList(criteria, methodName) as TEntityList; 

        } 

        protected TEntity FetchFirstAs(object criteria, string methodName) 

        { 

            return this.FetchFirst(criteria,methodName) as TEntity; 

        } 

        protected IEnumerable<TEntity> FetchList(object criteria, string methodName) 
        { 
            // 调用 " 数据门户 " 
            var list = DataPortalApi.Action(this.GetType(), methodName, criteria, this.DataPortalLocation) as IEnumerable<TEntity>; 
            return list; 
        } 

        protected TEntity FetchFirst(object criteria, string methodName) 

        { 

            var list = this.FetchList(criteria, methodName); 

            var last = list.DefaultIfEmpty<TEntity>() as TEntity; 

            return list.Count() > 0 ? last : null; 

        } 

        #endregion
} 

public abstract class RepositoryContext :DisposableObject,IRepositoryContext 

{ 

        #region Private Fields 

        private readonly Guid id = Guid.NewGuid(); 

        private readonly ThreadLocal<List<object>> localNewCollection = new ThreadLocal<List<object>>(() => new List<object>()); 

        private readonly ThreadLocal<List<object>> localModifiedCollection = new ThreadLocal<List<object>>(() => new List<object>()); 

        private readonly ThreadLocal<List<object>> localDeletedCollection = new ThreadLocal<List<object>>(() => new List<object>()); 

        private readonly ThreadLocal<bool> localCommitted = new ThreadLocal<bool>(() => true); 

        #endregion 

        #region Protected Properties 

        protected IEnumerable<object> NewCollection 

        { 

            get { return localNewCollection.Value; } 

        } 

        protected IEnumerable<object> ModifiedCollection 

        { 

            get { return localModifiedCollection.Value; } 

        } 

        protected IEnumerable<object> DeletedCollection 

        { 

            get { return localDeletedCollection.Value; } 

        } 

        #endregion 

        #region Protected Methods 

        protected void ClearRegistrations() 

        { 

            this.localNewCollection.Value.Clear(); 

            this.localModifiedCollection.Value.Clear(); 

            this.localDeletedCollection.Value.Clear(); 

        } 

        #endregion 

        #region IRepositoryContext Members 

        public Guid ID 

        { 

            get { return id; } 

        } 

        public virtual void RegisterNew(object obj) 

        { 

            localNewCollection.Value.Add(obj); 

            Committed = false; 

        } 

        public virtual void RegisterModified(object obj) 

        { 

            if (localDeletedCollection.Value.Contains(obj)) 

                throw new InvalidOperationException("The object cannot be registered as a modified object since it was marked as deleted."); 

            if (!localModifiedCollection.Value.Contains(obj) && !localNewCollection.Value.Contains(obj)) 

                localModifiedCollection.Value.Add(obj); 

            Committed = false; 

        } 

        public virtual void RegisterDeleted(object obj) 

        { 

            if (localNewCollection.Value.Contains(obj)) 

            { 

                if (localNewCollection.Value.Remove(obj)) 

                    return; 

            } 

            bool removedFromModified = localModifiedCollection.Value.Remove(obj); 

            bool addedToDeleted = false; 

            if (!localDeletedCollection.Value.Contains(obj)) 

            { 

                localDeletedCollection.Value.Add(obj); 

                addedToDeleted = true; 

            } 

            localCommitted.Value = !(removedFromModified || addedToDeleted); 

        } 

        #endregion 

        #region IUnitOfWork Members 

        public virtual bool DistributedTransactionSupported 

        { 

            get { return false; } 

        } 

        public virtual bool Committed 

        { 

            get { return localCommitted.Value; } 

            protected set { localCommitted.Value = value; } 

        } 

        public abstract void Commit(); 

        public abstract void Rollback(); 

        #endregion 

        protected override void Dispose(bool disposing) 

        { 

            if (disposing) 

            { 

                this.localCommitted.Dispose(); 

                this.localDeletedCollection.Dispose(); 

                this.localModifiedCollection.Dispose(); 

                this.localNewCollection.Dispose(); 

            } 
        } 
}
复制代码

 

LCLFramework框架之Repository扩展


clipboard[2]

复制代码
public class EntityFrameworkRepository<TEntity> : Repository<TEntity> 
        where TEntity : class, IEntity 
    { 
        private readonly IEntityFrameworkRepositoryContext efContext; 
        public EntityFrameworkRepository(IRepositoryContext context) 
            : base(context) 
        { 
            if (context is IEntityFrameworkRepositoryContext) 
                this.efContext = context as IEntityFrameworkRepositoryContext; 
        } 
        protected override void DoAdd(TEntity entity) 
        { 
            efContext.RegisterNew(entity); 
        } 
        protected override void DoRemove(TEntity entity) 
        { 
            efContext.RegisterDeleted(entity); 
        } 
        protected override void DoUpdate(TEntity entity) 
        { 
            efContext.RegisterModified(entity); 
        } 
        protected override IEnumerable<TEntity> DoGetAll(PagingInfo paging) 
        { 
            if (paging != null) 
            { 
                paging.TotalCount = efContext.Context.Set<TEntity>().Count(); 
                return efContext.Context.Set<TEntity>().OrderBy(t => t.ID).Skip(paging.PageNumber - 1 * paging.PageSize).Take(paging.PageSize).ToList(); 
            } 
            else 
            { 
                return efContext.Context.Set<TEntity>().ToList(); 
            } 
        } 
        protected override IEnumerable<TEntity> DoGet(Expression<Func<TEntity, bool>> predicate) 
        { 
            return efContext.Context.Set<TEntity>().Where(predicate).ToList(); 
        } 
        protected override TEntity DoGetByKey(params object[] keyValues) 
        { 
            return efContext.Context.Set<TEntity>().Find(keyValues); 
        } 
        protected override IEnumerable<TEntity> DoGetPage(Expression<Func<TEntity, bool>> predicate, PagingInfo paging = null) 
        { 
            if (paging != null) 
            { 
                paging.TotalCount = efContext.Context.Set<TEntity>().Count(); 
                return efContext.Context.Set<TEntity>().OrderBy(predicate).Skip((paging.PageNumber - 1) * paging.PageSize).Take(paging.PageSize).ToList(); 
            } 
            else 
            { 
                return efContext.Context.Set<TEntity>().OrderBy(predicate).ToList(); 
            } 
        } 
    } 
public interface IEntityFrameworkRepositoryContext : IRepositoryContext 
{ 
        DbContext Context { get; } 
} 
public class EntityFrameworkRepositoryContext : RepositoryContext, IEntityFrameworkRepositoryContext 
    { 
        #region Private Fields 
        private readonly DbContext efContext; 
        private readonly object sync = new object(); 
        #endregion 
        #region Ctor 
        public EntityFrameworkRepositoryContext(DbContext efContext) 
        { 
            this.efContext = efContext; 
        } 
        #endregion 
        #region Protected Methods 
        protected override void Dispose(bool disposing) 
        { 
            if (disposing) 
            { 
                efContext.Dispose(); 
            } 
            base.Dispose(disposing); 
        } 
        #endregion 
        #region IEntityFrameworkRepositoryContext Members 
        public DbContext Context 
        { 
            get { return this.efContext; } 
        } 
        #endregion 
        #region IRepositoryContext Members 
        public override void RegisterNew(object obj) 
        { 
            this.efContext.Entry(obj).State = System.Data.Entity.EntityState.Added; 
            Committed = false; 
        } 
        public override void RegisterModified(object obj) 
        { 
            this.efContext.Entry(obj).State = System.Data.Entity.EntityState.Modified; 
            Committed = false; 
        } 
        public override void RegisterDeleted(object obj) 
        { 
            this.efContext.Entry(obj).State = System.Data.Entity.EntityState.Deleted; 
            Committed = false; 
        } 
        #endregion 
        #region IUnitOfWork Members 
        public override bool DistributedTransactionSupported 
        { 
            get { return true; } 
        } 
        public override void Commit() 
        { 
            if (!Committed) 
            { 
                lock (sync) 
                { 
                    efContext.SaveChanges(); 
                } 
                Committed = true; 
            } 
        } 
        public override void Rollback() 
        { 
            Committed = false; 
        } 
        #endregion 
    }
复制代码

  LCLFramework框架之Repository使用


复制代码
public class Village : DomainEntity 
    { 
        public string Name { get; set; } 
    }   
public interface IVillageRepository : IRepository<Village> 
    { 
        //仓库扩展 
        List<Village> GetTest(); 
    } 
    [Serializable] 
    [RepositoryFor(typeof(Village))] 
    public class VillageRepository : EntityFrameworkRepository<Village>, IVillageRepository 
    { 
        private readonly IRepositoryContext context; 
        public VillageRepository(IRepositoryContext context) 
            : base(context) 
        { 
           this.context = context; 
        } 
        //仓库扩展方法 
        public List<Village> GetTest() 
        { 
            return new List<Village>(); 
        } 
    }
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值