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 = !(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扩展
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>();
}
}
LCLFramework框架之Repository模式的更多相关文章
- LCLFramework框架之Service模式
Service模式介绍 领域中的一些概念不太适合建模为对象,即归类到实体对象或值对象,因为它们本质上就是一些操作,一些动作,而不是事物.这些操作或动作往往会涉及到多个领域对象,并且需要协调这些领域对象 ...
- LCLFramework框架之Plugin模式
插件应用架构概述 基于LCLFramework插件框架的应用由以下三个部分构成: (1)主程序:针对特定应用环境(Web.WinForm等应用环境),加载启动插件,获取插件入口,运行入口程序. (2) ...
- LCLFramework框架 1.1 Pre-Alpha 源码公布
使用开发框架的好处:1.框架在技术上为软件系统提供了完整的模式实践2.框架为团队提供了合理可行的软件开发过程模式3.框架的应用大大提高了团队的开发效率,团队只需要关注与领域相关的业务实现,而无需关注具 ...
- (转)MVC中的Repository模式
1.首先创建一个空的MVC3应用程序,命名为MyRepository.Web,解决方案命名为MyRepository. 2.添加一个类库项目,命名为MyRepository.DAL,添加一个文件夹命名 ...
- Laravel Repository 模式
Repository 模式 为了保持代码的整洁性和可读性,使用Repository Pattern 是非常有用的.事实上,我们也不必仅仅为了使用这个特别的设计模式去使用Laravel,然而在下面的场景 ...
- MVC中的Repository模式
1.首先创建一个空的MVC3应用程序,命名为MyRepository.Web,解决方案命名为MyRepository. 2.添加一个类库项目,命名为MyRepository.DAL,添加一个文件夹命名 ...
- MVC Repository模式
近来发现很多ASP.NET MVC的例子中都使用了Repository模式,比如Oxite,ScottGu最近发布的免费的ASP.NET MVC教程都使用了该模式.就简单看了下. 在<企业架构模 ...
- 在 Laravel 5 中使用 Repository 模式实现业务逻辑和数据访问的分离
1.概述 首先需要声明的是设计模式和使用的框架以及语言是无关的,关键是要理解设计模式背后的原则,这样才能不管你用的是什么技术,都能够在实践中实现相应的设计模式. 按照最初提出者的介绍,Reposito ...
- Repository模式(转载)
近来发现很多ASP.NET MVC的例子中都使用了Repository模式,比如Oxite,ScottGu最近发布的免费的ASP.NET MVC教程都使用了该模式.就简单看了下. 在<企业架构模 ...
随机推荐
- json jackson
1.引入依赖 <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId&g ...
- Fragment的基本用法
一.Fragment主要用到的API: 1.Fragment 类-----用来创建碎片 2.FragmentManager 类 ----为管理Activity中Fragment,用于Activity与 ...
- 用代码控制UI界面
public class MainActivity extends Activity { //当第一次创建Activity时回调该方法 @Override protected void ...
- golang 值得注意的地方(2则)
golang 的语法和使用方式都非常简单明了,没有花哨的语法糖,也没有多余的关键字. 但是即使是这么简洁的语言,仍然有一些不那么直白,需要注意的地方,比如下面2点. interface 赋值 nil ...
- c#中的static
1.C# 不支持静态局部变量(在方法范围内声明的变量). 2.static类一般用于与状态无关的类.那么,什么是与状态无关的类?我的理解是当一个类中没有属性,只有方法的的时候,就可以认为这个类是与状态 ...
- 使用NHibernate(9)-- 缓存
1,对象状态. 作为基础,还是先看一下对象的状态吧.主要涉及到三个名词,瞬时.持久.托管. 瞬时态:对象刚创建,Session还不知道这个对象的存在.可以通过调用ISession的Save等方法可以转 ...
- C#设计模式(18)——中介者模式(Mediator Pattern)
一.引言 在现实生活中,有很多中介者模式的身影,例如QQ游戏平台,聊天室.QQ群和短信平台,这些都是中介者模式在现实生活中的应用,下面就具体分享下我对中介者模式的理解. 二. 中介者模式的介绍 2.1 ...
- Python爬虫 -- 抓取电影天堂8分以上电影
看了几天的python语法,还是应该写个东西练练手.刚好假期里面看电影,找不到很好的影片,于是有个想法,何不搞个爬虫把电影天堂里面8分以上的电影爬出来.做完花了两三个小时,撸了这么一个程序.反正蛮简单 ...
- 你在用什么思想编码:事务脚本 OR 面向对象?
最近在公司内部做技术交流的时候,说起技能提升的问题,调研大家想要培训什么,结果大出我意料,很多人想要培训:面向对象编码.于是我抛出一个问题:你觉得我们现在的代码是面向对象的吗?有人回答:是,有人回答否 ...
- 清爽绿色格调图文box通用样式
今天是端午节,小菜献上一款剽窃的box样式,祝大家端午快乐! 此box样式以绿色为主要色调,清新自然,适合大多数设计场景. 此box算是比较高级的了,box中的列表是图文列表,可以显示一张小图片,然后 ...