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

名词介绍:首先我们必须了解一点领域驱动(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共同所有,转载请标明出处

posted @ 2013-05-10 13:05  egojit  阅读(6030)  评论(11编辑  收藏  举报
分享按钮