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共同所有,轉載請標明出處


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM