首页 > 代码库 > LCLFramework框架之Repository模式
LCLFramework框架之Repository模式
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仓库,对于个人来使用已经足够了。
LCLFramework框架之Repository模式设计代码
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 = http://www.mamicode.com/!(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 = http://www.mamicode.com/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扩展
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使用
[Serializable]
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>();
}
}
LCLFramework框架之Repository模式