LCLFramework框架之Repository模式

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仓库,对于个人来使用已经足够了。

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使用


[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>();

}

}

时间: 2024-12-24 07:04:57

LCLFramework框架之Repository模式的相关文章

LCLFramework框架之Plugin模式

Plugin模式在示例中的实际目的小结一下 Plugin模式是架构模式,在设计架构时,才有参考价值: Plugin模式主要是实现单一职责的封装,和扩展应用程序: Plugin与扩展的区别 插件稍不同于扩展(extension),插件通常依赖于主应用程序的接口,有一个它们可以运行的确定的界限.扩展则通常有更少的限制,也可以提供它们自己的接口.相同的是,它们通常都用来减少主应用程序的大小.提供一些可选的功能. 这里不得不提到Mozilla Firefox 和相关软件.它们使用一个叫做Add-on的名

LCLFramework框架之Service模式

Service模式介绍 领域中的一些概念不太适合建模为对象,即归类到实体对象或值对象,因为它们本质上就是一些操作,一些动作,而不是事物.这些操作或动作往往会涉及到多个领域对象,并且需要协调这些领域对象共同完成这个操作或动作.如果强行将这些操作职责分配给任何一个对象,则被分配的对象就是承担一些不该承担的职责,从而会导致对象的职责不明确很混乱.但是基于类的面向对象语言规定任何属性或行为都必须放在对象里面. 所以我们需要寻找一种新的模式来表示这种跨多个对象的操作,DDD认为服务是一个很自然的范式用来对

Repository模式

近来发现很多ASP.NET MVC的例子中都使用了Repository模式,比如Oxite,ScottGu最近发布的免费的ASP.NET MVC教程都使用了该模式.就简单看了下. 在<企业架构模式>中,译者将Repository翻译为资源库.给出如下说明:通过用来访问领域对象的一个类似集合的接口,在领域与数据映射层之间进行协调. 在<领域驱动设计:软件核心复杂性应对之道>中,译者将Repository翻译为仓储,给出如下说明:一种用来封装存储,读取和查找行为的机制,它模拟了一个对象

基于ASP.NET WPF技术及MVP模式实战太平人寿客户管理项目开发(Repository模式)

亲爱的网友,我这里有套课程想和大家分享,如果对这个课程有兴趣的,可以加我的QQ2059055336和我联系. 课程背景 本课程是教授使用WPF.ADO.NET.MVVM技术来实现太平人寿保险有限公司保险客户管理系统,是学习WPF开发中的一门主打课程之一. WPF是一个框架,它供程序员开发出媲美Mac程序的酷炫界面. Blend是一种工具,可以在美工板上绘制形状.路径和控件,然后修改其外观和行为,从而直观地设计应用程序 Repository\MVVM\MVP设计模式是WPF常用的系统架构 Auto

MVC中的Repository模式

1.首先创建一个空的MVC3应用程序,命名为MyRepository.Web,解决方案命名为MyRepository. 2.添加一个类库项目,命名为MyRepository.DAL,添加一个文件夹命名为Repository来存放业务逻辑. 3.继续添加一个类库项目,命名为MyRepository.Domain,添加两个文件夹Models和Infrastructure. Models来存放实体,Infrastructure来存放几个基本的类.现在目录结构已经搭建好了. 4.用NuGet确保三个项目

基于Repository模式设计项目架构—你可以参考的项目架构设计

关于Repository模式,直接百度查就可以了,其来源是<企业应用架构模式>.我们新建一个Infrastructure文件夹,这里就是基础设施部分,EF Core的上下文类以及Repository层都放在这里面.新建一个IReposotory的接口,其内容就是封装了基本的CRUD: public interface IRepository<TEntity> where TEntity : class { ///获取当前实体的查询数据集 IQueryable<TEntity&

【.NET】EF框架之三种模式

使用EF之前必须要对EF有个宏观的了解.学习任何一种技术都要像门卫一样问几个问题. 第一,它是谁? 第二,从哪里来? 第三,到哪里去? 默念一遍:不谋全局者,不足谋一域. 今天老师宏观给讲了一下EF的好处,抛出为什么要用EF的问题,我们的回答仅仅是概念和技术上的浅显的认识,老师的话我并未全部理解.先来整理一下自己所认识的EF吧. Entity Framework是ORMapping的一种具体实现,那ORMapping又是什么呢?ORM--ObjectRelation Mapping,即对象关系映

LCLFramework框架之IOC

LCLFramework框架之依赖注入(IOC)职责 依赖注入(Dependency Injection,简称DI) 依赖查找(Dependency Lookup) 控制反转 LCLFramework框架之依赖注入(IOC)设计 网上有很多的IOC框架如何让用户选择自己熟悉的IOC框架了,那LCL就需要提供可扩展的IOC应该如何让框架注入自己熟悉的IOC框架呢? 下图是基本的IOC扩展契约,所有的第三方都要实现IObjectContainer契约,下图中实现了,Unity,TinyIoc两个第三

LCLFramework框架 1.1 Pre-Alpha 源码公布

LCLFramework 框架简要说明: LCL 是一个管理类软件的快速开发框架,其目标主要专注于:1. 快速开发:    DDD.界面自动生成.数据库自动生成与升级.易用的业务逻辑编写框架.2. 产品线工程:    插件化业务模块积累(内置一个权限控制插件模块).客户化二次开发.实施配置平台.3. 一套代码,可同时生成并运行 C/S.单机版.B/S 三种应用程序.    C/S版本 与 单机版 代码重用率 100%.    C/S版本 与 B/S版本 重用服务端代码(完全重用服务层以下代码.结