在閱讀本文章以前,你能夠先閱讀:數據庫
倉儲封裝了基礎設施來提供查詢和持久化聚合操做。 它們集中提供常見的數據訪問功能,從而提供更好的可維護性,並將用於訪問數據庫的基礎結構或技術與領域模型層分離。 建立數據訪問層和應用程序的業務邏輯層之間的抽象層。 實現倉儲可以讓你的應用程序對數據存儲介質的更改不敏感。編程
直接訪問數據:緩存
使用倉儲優勢:函數
實現基本的增刪改查及事務的提交和回滾單元測試
首先,定義接口測試
/// <summary> /// IRepository提供應用程序倉儲模式基本操做的接口 /// </summary> public interface IRepository { #region Methods void Entry<T>(T t) where T : AggregateRoot; void Save(); T Get<T>(Guid id, Func<IQueryable<T>, IQueryable<T>> includes = null) where T : AggregateRoot; T Get<T>(Expression<Func<T, bool>> where, Func<IQueryable<T>, IQueryable<T>> includes = null) where T : AggregateRoot; IQueryable<T> Query<T>(Expression<Func<T, bool>> filter=null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy=null, Func<IQueryable<T>, IQueryable<T>> includes=null) where T : AggregateRoot; IQueryable<T> QueryByPage<T>(int pageIndex, int pageSize, Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, Func<IQueryable<T>, IQueryable<T>> includes = null) where T : AggregateRoot; void BeginTransaction(); void Commit(); void Rollback(); #endregion }
最後,實現以上接口ui
public class Repository : IDisposable, IRepository { #region Private Fields private readonly DbContext context; private IDbContextTransaction transaction; #endregion #region Constructors public Repository(DbContext context) { this.context = context ?? throw new ArgumentNullException(nameof(context)); } #endregion #region IRepository<T> Members public void Entry<T>(T t) where T : AggregateRoot { switch (t.AggregateState) { case AggregateState.Added: context.Entry(t).State = EntityState.Added; break; case AggregateState.Deleted: context.Entry(t).State = EntityState.Deleted; break; default: context.Entry(t).State = EntityState.Modified; break; } } public void Save() { context.SaveChanges(); } public T Get<T>(Guid id, Func<IQueryable<T>, IQueryable<T>> includes = null) where T : AggregateRoot { return Get(w => w.Id.Equals(id), includes: includes); } public T Get<T>(Expression<Func<T, bool>> filter, Func<IQueryable<T>, IQueryable<T>> includes = null) where T : AggregateRoot { return Query(filter, includes: includes).SingleOrDefault(); } public IQueryable<T> Query<T>(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, Func<IQueryable<T>, IQueryable<T>> includes = null) where T : AggregateRoot { IQueryable<T> query = context.Set<T>(); if (filter != null) { query = query.Where(filter); } if (includes != null) { query = includes(query); } if (orderBy != null) { query = orderBy(query); } return query; } public IQueryable<T> QueryByPage<T>(int pageIndex, int pageSize, Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, Func<IQueryable<T>, IQueryable<T>> includes = null) where T : AggregateRoot { var query = Query(filter, orderBy, includes) .Skip(pageSize * (pageIndex - 1)) .Take(pageSize); return query; } public void BeginTransaction() { transaction = context.Database.BeginTransaction(); } public void Rollback() { transaction.Rollback(); } public void Commit() { transaction.Commit(); } public void Dispose() { if (transaction != null) { transaction.Dispose(); } context.Dispose(); } #endregion }
爲數據庫上下文和事務上下文聲明類變量:this
private readonly DbContext context; private IDbContextTransaction transaction;
構造函數接受數據庫上下文實例:設計
public Repository(DbContext context) { this.context = context ?? throw new ArgumentNullException(nameof(context)); }
Get分爲經過ID查詢或過濾條件進行查詢,返回序列中的惟一元素:code
public T Get<T>(Guid id, Func<IQueryable<T>, IQueryable<T>> includes = null) where T : AggregateRoot { return Get(w => w.Id.Equals(id), includes: includes); } public T Get<T>(Expression<Func<T, bool>> filter, Func<IQueryable<T>, IQueryable<T>> includes = null) where T : AggregateRoot { return Query(filter, includes: includes).SingleOrDefault(); }
Query 方法使用 lambda 表達式來容許調用代碼指定篩選條件,使用一列來對結果進行排序,容許調用方爲預先加載導航屬性列表:
// 代碼 Expression<Func<T, bool>> filter 意味着調用方將基於 AggregateRoot 類型提供 lambda 表達式,而且此表達式將返回一個布爾值。 // 代碼 Func<IQueryable<T>, IOrderedQueryable<T>> orderBy 也意味着調用方將提供 lambda 表達式。 但在這種狀況下,表達式的輸入是 AggregateRoot 類型的 IQueryable 對象。 表達式將返回 IQueryable 對象的有序版本。 // 代碼 Func<IQueryable<T>, IQueryable<T>> includes 也意味着調用方將提供 lambda 表達式。 容許預先加載導航屬性列表。 public IQueryable<T> Query<T>(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, Func<IQueryable<T>, IQueryable<T>> includes = null) where T : AggregateRoot { IQueryable<T> query = context.Set<T>(); if (filter != null) { query = query.Where(filter); } if (includes != null) { query = includes(query); } if (orderBy != null) { query = orderBy(query); } return query; }
Entry 方法使用 AggregateRoot.AggregateState 來置 context.Entry(t).State 狀態,完成增刪改
public void Entry<T>(T t) where T : AggregateRoot { switch (t.AggregateState) { case AggregateState.Added: context.Entry(t).State = EntityState.Added; break; case AggregateState.Deleted: context.Entry(t).State = EntityState.Deleted; break; default: context.Entry(t).State = EntityState.Modified; break; } }
Save 等其餘方法也相似實現。