名詞介紹:首先我們必須瞭解一點領域驅動(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.Repositories13 {14 /// <summary>15 /// 倉儲介面16 /// </summary>17 /// <typeparam name="TAggregateRoot">倉儲根類型</typeparam>18 public interface IRepository<TAggregateRoot>19 where TAggregateRoot : class, IAggregateRoot20 {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 by54 /// 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共同所有,轉載請標明出處