名詞介紹:首先我們必須了解一點領域驅動(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共同所有,轉載請標明出處