Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LCLFramework框架之Repository模式 #1

Open
luomingui opened this issue Sep 30, 2015 · 0 comments
Open

LCLFramework框架之Repository模式 #1

luomingui opened this issue Sep 30, 2015 · 0 comments

Comments

@luomingui
Copy link
Owner

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

Repository模式是架构模式,在设计架构时,才有参考价值;
Repository模式主要是封装数据查询和存储逻辑;
Repository模式实际用途:更换、升级ORM 引擎,不影响业务逻辑;
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 where TEntity : class, IEntity
{
IRepositoryContext Context { get; }
void Create(TEntity entity);
void Delete(TEntity entity);
void Update(TEntity entity);
IEnumerable Get(Expression<Func<TEntity, bool>> predicate);
IEnumerable GetAll(PagingInfo paging = null);
TEntity GetByKey(params object[] keyValues);
IEnumerable 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类的红色部分是与WCF交互的代码。通过“数据门户”来决定是本地执行还是网络执行。

*/

public abstract partial class Repository : IRepository
where TEntity : class, IEntity
{
///

/// 是否声明本仓库为本地仓库(客户端只在客户端查询,服务端在服务端查询)
/// </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 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 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 : Repository
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 DoGetAll(PagingInfo paging)
{
if (paging != null)
{
paging.TotalCount = efContext.Context.Set().Count();
return efContext.Context.Set().OrderBy(t => t.ID).Skip(paging.PageNumber - 1 * paging.PageSize).Take(paging.PageSize).ToList();
}
else
{
return efContext.Context.Set().ToList();
}
}
protected override IEnumerable DoGet(Expression<Func<TEntity, bool>> predicate)
{
return efContext.Context.Set().Where(predicate).ToList();
}
protected override TEntity DoGetByKey(params object[] keyValues)
{
return efContext.Context.Set().Find(keyValues);
}
protected override IEnumerable DoGetPage(Expression<Func<TEntity, bool>> predicate, PagingInfo paging = null)
{
if (paging != null)
{
paging.TotalCount = efContext.Context.Set().Count();
return efContext.Context.Set().OrderBy(predicate).Skip((paging.PageNumber - 1) * paging.PageSize).Take(paging.PageSize).ToList();
}
else
{
return efContext.Context.Set().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
{
//仓库扩展
List GetTest();
}
[Serializable]
[RepositoryFor(typeof(Village))]
public class VillageRepository : EntityFrameworkRepository, IVillageRepository
{
private readonly IRepositoryContext context;
public VillageRepository(IRepositoryContext context)
: base(context)
{
this.context = context;
}
//仓库扩展方法
public List GetTest()
{
return new List();
}
}
复制代码

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant