ASP.NET MVC4+EF系列之六仓储实现 IRepository 和 Repository

作者: egojit
发布时间:2015-06-17 11:39:49

名词介绍:首先我们必须了解一点领域驱动(DDD)相关知识,至少要对一些名词熟悉,我上传的源代码的注释包含了很多这些名词。例如仓储仓储上下文,仓储根领域对象,以及什么领域对象可以考虑作为仓储根。这里我就按我的理解做个粗浅的介绍。不当之处请原谅。比较DDD不是一朝一夕能领悟的东西,需要理论加实践的不断磨合,我这里只是简单的DDD。

  1.领域对象:就是我们业务中的一个个对象。我想这不用多加解释了。

  2.仓储根:就是能被直接操作到数据库的领域对象,它是领域对象的子集。业务当中的所有操作都是对仓储根的操作。也只有仓储根能被放进仓储,让后被固化到数据库。在不同的业务中仓储根是不同的,利于在订单中订单对象肯定就是仓储根,但是订单地址就不是,订单地址只是作为订单的属性而存在。我们框架中通过这个TAggregateRoot借口去

  3.仓储:其实就是领域对象存放的地方。每一个领域对象都有自己的仓储。这里面存储了很多同一类型的对象

  4.仓储上下文:不通仓储存放的地方,对不通仓储根的仓储进行管理。

更多的名词我就不一一介绍,我只介绍我用的比较多的。更多领域驱动相关,推荐大家网上学习了解下

一.IRepository 和 Repositor概述

  Repository顾名思义就是仓储,Repository继承了IRepository接口,并且实现了一套通用的操作仓储根的方法,通过这些方法我们可以很灵活的操作数据库。Repository只是基础的仓储。至于具体的通过EF还是NH去实现数据的固化和查询。我们主要继承Repository这个类就行了。Repository是一个抽象类。只能被继承。让后去实现各种具体的仓储,是用EF还是用NH操作数据那就取决于我们了。IRepository为仓储提供了一套标准。我么这里选择了EF,这种后面详述。

  1.IRepository基本仓储标准

  

 1 /*****************************************************   2  * 作者:egojit   3  * 日期:2012-7-13   4  * 描述:仓储接口   5  * ***************************************************/   6 using System;   7 using System.Collections.Generic;   8 using System.Linq.Expressions;   9 using EgojitFramework.Domain.Specifications;  10   11   12 namespace EgojitFramework.Domain.Repositories  13 {  14     /// <summary>  15     /// 仓储接口  16     /// </summary>  17     /// <typeparam name="TAggregateRoot">仓储根类型</typeparam>  18     public interface IRepository<TAggregateRoot>  19         where TAggregateRoot : class, IAggregateRoot  20     {  21         /// <summary>  22         ///获取仓储上下文实例  23         /// </summary>  24         IRepositoryContext Context { get; }  25         /// <summary>  26         /// 添加一个仓储根到仓储中  27         /// </summary>  28         /// <param name="aggregateRoot">仓储根.</param>  29         void Add(TAggregateRoot aggregateRoot);  30         /// <summary>  31         /// 通过Key从仓储中获取仓储根实例  32         /// </summary>  33         /// <param name="key">key.</param>  34         /// <returns>仓储根实例</returns>  35         TAggregateRoot GetByKey(Guid key);  36         /// <summary>  37         /// 从仓储中获取所有的仓储根实例  38         /// </summary>  39         /// <returns>仓储根实例列表</returns>  40         IEnumerable<TAggregateRoot> GetAll();  41         /// <summary>  42         /// 分页从仓储中获取所有的仓储根实例  43         /// </summary>  44         /// <param name="pageNumber">页号</param>  45         /// <param name="pageSize">每页的数量</param>  46         /// <returns>指定页的仓储根列表</returns>  47         IEnumerable<TAggregateRoot> GetAll(int pageNumber, int pageSize);  48         /// <summary>  49         /// 从仓储中获取所有的仓储根实例并且排序  50         /// </summary>  51         /// <param name="sortPredicate">The sort predicate which is used for sorting.</param>  52         /// <param name="sortOrder">The <see cref="Apworks.SortOrder"/> enumeration which specifies the sort order.</param>  53         /// <returns>All the aggregate roots got from the repository, with the aggregate roots being sorted by  54         /// using the provided sort predicate and the sort order.</returns>  55         IEnumerable<TAggregateRoot> GetAll(Expression<Func<TAggregateRoot, dynamic>> sortPredicate, SortOrder sortOrder);  56         /// <summary>  57         /// 分页从仓储中获取所有的仓储根实例并且排序  58         /// </summary>  59         /// <param name="sortPredicate">排序条件</param>  60         /// <param name="sortOrder">排序方式</param>  61         /// <param name="pageNumber">页号</param>  62         /// <param name="pageSize">每页数量</param>  63         /// <returns>排序后的仓储根列表</returns>  64         IEnumerable<TAggregateRoot> GetAll(Expression<Func<TAggregateRoot, dynamic>> sortPredicate, SortOrder sortOrder, int pageNumber, int pageSize);  65 }  66 }

当然这个接口中远不止这么多代码。更多请参照源码。从

 /// <summary>      /// 仓储接口      /// </summary>      /// <typeparam name="TAggregateRoot">仓储根类型</typeparam>      public interface IRepository<TAggregateRoot>          where TAggregateRoot : class, IAggregateRoot

这行代码我们很容易看出来IRepository类中的操作的对象都是基础自TAggregateRoot接口的仓储根,这就很好的限制了普通实体的数据库操作。

   2.继承自IRepository接口的Repository仓储类

  部分代码如下:

using System;  using System.Collections.Generic;  using System.Linq;  using System.Text;  using EgojitFramework.Domain.Specifications;  using System.Linq.Expressions;  /*****************************************************   * 作者:egojit   * 日期:2012-7-13   * 描述:仓储抽象类   * ***************************************************/  namespace EgojitFramework.Domain.Repositories  {      /// <summary>      /// 仓储基础类      /// </summary>      /// <typeparam name="TAggregateRoot">The type of the aggregate root on which the repository operations      /// should be performed.</typeparam>      public abstract class Repository<TAggregateRoot> : IRepository<TAggregateRoot>          where TAggregateRoot : class, IAggregateRoot      {          #region 私有字段          private readonly IRepositoryContext context;          #endregion            #region 属性          /// <summary>          /// 仓储上下文的一个实例          /// </summary>          /// <param name="context">被这个仓储使用的仓储上下文</param>          public Repository(IRepositoryContext context)          {              this.context = context;          }          #endregion            #region 私有方法          /// <summary>          /// 添加一个仓储根到仓储          /// </summary>          /// <param name="aggregateRoot">被添加的仓储根</param>          protected abstract void DoAdd(TAggregateRoot aggregateRoot);          /// <summary>          /// 通过Key在这个仓储中获取仓储根          /// </summary>          /// <param name="key">Key</param>          /// <returns>仓储实例</returns>          protected abstract TAggregateRoot DoGetByKey(Guid key);  。。。。。。此次省去更多代码  }  }

通过代码我们很容易知道它操作的也是仓储根,并且继承了IRepository接口,而且它是抽象的,必须被继承去实现,这样我们就为基于EF或者是NH或者其它实现的仓储提供了一种很容易的途径,只要在他的子类中去重现其中的方法就行了。我们看到通过构造函数将仓储上下文带到了这个类中。

这节就介绍这个基本仓储,下个节。将介绍仓储中的事务管理。(次阶段源代码下载)

版权:归博客园和egojit共同所有,转载请标明出处

来源:http://www.cnblogs.com/egojit/archive/2013/05/10/3070913.htm

推荐: