一直都想寫博客,惋惜真的太懶了或者對本身的描述水平不太自信,因此。。。一直都是不想寫的狀態,關於領域驅動的東西看了很多,可是因爲本身水平太差加上工做中實在用不到,因此一直處於擱置狀態,最近心血來潮忽然想從新寫一個本身的項目架構,因而開始了新一論的學習歷程。數據庫
在設計以前我理了一下本身的大體需求也參考了不一樣人的項目架構,在此特別感謝郭明峯的OSharp給個人啓示,每一個人對架構的需求和使用習慣都是不一至的,在不一樣大小的項目上使用的架構也不盡相同,如何取捨性能、開發速度及維護性的問題上每開發者都在本身心中有一杆秤,下面談談我理想中的架構,它應該提供一些經常使用的操做封裝及各類工具方便實現多個功能,他應該包括數據操做的方便處理,他應該提供日誌及緩存的處理功能,它的每種實現是本身換的但又得具備默認值讓我在作私單的時候更快捷方便,基於以上特色因而總結了以下模塊:緩存
1,工具庫:提供了各類經常使用操做,如字符串截取,各類驗證之類的helper類架構
2,核心庫:提供緩存日誌數據的接口及緩存日誌的基礎實現app
3,WEB庫:針對網站相關的擴展及操做封裝異步
4,MVC庫:針對MVC網站的相關擴展及操做封裝async
5,基礎數據庫模塊實現庫(如:EF)ide
回到每一個架構的重點:數據訪問模塊上來,如今比較流行使用EF+ IUnitOfWork+Repository來實現數據的處理,誠然這種方式讓每個模塊相互的依賴變得更小,更方便測試,更XXX,可是在個人實踐中,仍是發現他真的麻煩,在我作一箇中小項目的時候,添加一個普通的表不得不去添加實體,實體配置,倉儲接口,倉儲實現,服務接口,服務實現,controller viewmodel,view一系列下來即使是拷貝也是很是慢,即便咱們能夠用代碼生成器,我仍是以爲太麻煩了。固然Repository模式的反對者也很多,做爲一種數據操做的隔離手段,我我的以爲Repository仍是頗有必要存在的,通過各類取捨,最後本身使用了一種折中的方式來使用Repository,個人方式是使用IStore來代替IUnitOfWork,本質是同樣的,只是IStore實現的功能要多一些,同時使用了IStore使得咱們能夠很容易的替換咱們的數據庫功能實現,以下圖:工具
因爲通常的項目不須要一人寫定義一人寫實現,因此直接省去了IUserRepository及IUserService這種並不會修改實現的接口,固然若是有團隊共同開發的時候使用也是徹底沒有問題的,有了以上的圖就開以開始實現代碼了:性能
IDataStore:學習
1 /// <summary> 2 /// 數據存儲器接口 3 /// </summary> 4 public interface IStore : IDisposable 5 { 6 #region UnitOfWork 7 /// <summary> 8 /// 獲取或設置 是否開啓事務提交 9 /// </summary> 10 bool TransactionEnabled { get; set; } 11 /// <summary> 12 /// 提交操做 13 /// </summary> 14 bool Commit(); 15 /// <summary> 16 /// 異步提交 17 /// </summary> 18 Task<bool> CommitAsync(); 19 #endregion 20 21 #region 基礎操做 22 /// <summary> 23 /// 添加對像 24 /// </summary> 25 void Add<TEntity>(TEntity entity) where TEntity : class; 26 /// <summary> 27 /// 更新對像 28 /// </summary> 29 void Update<TEntity>(TEntity entity) where TEntity : class; 30 /// <summary> 31 /// 刪除對像 32 /// </summary> 33 void Remove<TEntity>(TEntity entity) where TEntity : class; 34 #endregion 35 36 #region 查詢操做 37 /// <summary> 38 /// 獲取數據集查詢對像 39 /// </summary> 40 IQueryable<TEntity> GetQueryEntities<TEntity, TKey>() where TEntity : class; 41 #endregion 42 }
IRepository:
/// <summary> /// 倉儲接口 /// </summary> /// <typeparam name="TEntity">實體類型</typeparam> /// <typeparam name="TKey">實體主鍵類型</typeparam> public interface IRepository<TEntity, TKey> { #region 屬性 /// <summary> /// 獲取當前數據存儲器 /// </summary> IStore DataStore { get; } /// <summary> /// 獲取當前實體的查詢數據集 /// </summary> IQueryable<TEntity> Entities { get; } #endregion #region 基礎操做 /// <summary> /// 添加實體到倉庫 /// </summary> void Add(TEntity entity); /// <summary> /// 更新倉庫中的實體 /// </summary> void Update(TEntity entity); /// <summary> /// 從倉庫刪除指定key的實體 /// </summary> void Remove(TEntity entity); #endregion #region 查詢 /// <summary> /// 獲取指定key的實體 /// </summary> TEntity FindByKey(TKey key); #endregion }
RepositroyBase:
1 /// <summary> 2 /// 倉儲基類 3 /// </summary> 4 public abstract class RepositoryBase<TEntity, TKey> : IRepository<TEntity, TKey> 5 where TEntity : EntityBase<TKey>, new() 6 { 7 8 public IStore DataStore { get; set; } 9 10 public IQueryable<TEntity> Entities 11 { 12 get { return this.DataStore.GetQueryEntities<TEntity, TKey>(); } 13 } 14 15 public void Add(TEntity entity) 16 { 17 this.DataStore.Add<TEntity>(entity); 18 } 19 20 public void Update(TEntity entity) 21 { 22 this.DataStore.Update<TEntity>(entity); 23 } 24 25 public void Remove(TEntity entity) 26 { 27 this.DataStore.Remove<TEntity>(entity); 28 } 29 30 public TEntity FindByKey(TKey key) 31 { 32 return this.Entities.Where(t => t.Id.Equals(key)).SingleOrDefault(); 33 } 34 }
固然BaseEntity這種東西就看本身愛好添加了,按key刪除,按條件更新的方法這裏就不寫了
,另外關於返回Repository返回IEnumerable仍是IQueryable這個問題我我的認爲若是不按照DDD的的標準來看,一個倉庫每次拿你想要的東西仍是給你一個通道你想拿多少就拿多少本質上都是能夠的,不過對於隔離開發人員直接操做數據確實存在隱患,不過誰叫他簡單呢?看完定義,而後若是要使用EF作爲ORM來操做數據庫或者任意繼承至IDataStore的庫來完成數據操做,不過這裏要本身寫的話,解析表達式仍是有點困難的。。貼下簡單EF基類的簡單實現:
1 /// <summary> 2 /// EF數據存儲器(抽象類) 3 /// </summary> 4 public abstract class EFDataStore : DbContext, IStore 5 { 6 #region DbContext 7 protected EFDataStore() { } 8 protected EFDataStore(DbCompiledModel model) : base(model) { } 9 public EFDataStore(string nameOrConnectionString) : base(nameOrConnectionString) { } 10 public EFDataStore(DbConnection existingConnection, bool contextOwnsConnection) : base(existingConnection, contextOwnsConnection) { } 11 public EFDataStore(ObjectContext objectContext, bool dbContextOwnsObjectContext) : base(objectContext, dbContextOwnsObjectContext) { } 12 public EFDataStore(string nameOrConnectionString, DbCompiledModel model) : base(nameOrConnectionString, model) { } 13 public EFDataStore(DbConnection existingConnection, DbCompiledModel model, bool contextOwnsConnection) : base(existingConnection, model, contextOwnsConnection) { } 14 /// <summary> 15 /// 實體映射集合 16 /// </summary> 17 public IEnumerable<IEntityMapper> EntityConfigurations { get; set; } 18 19 protected override void OnModelCreating(DbModelBuilder modelBuilder) 20 { 21 //foreach (var mapper in EntityConfigurations) 22 //{ 23 // mapper.RegistTo(modelBuilder.Configurations); 24 //} 25 } 26 #endregion 27 28 public bool TransactionEnabled { get; set; } 29 30 public IQueryable<TEntity> GetQueryEntities<TEntity, TKey>() where TEntity : class 31 { 32 return this.Set<TEntity>(); 33 } 34 35 public bool Commit() 36 { 37 var r = this.SaveChanges(); 38 //this.Dispose(); 39 return r > 0; 40 } 41 42 public async Task<bool> CommitAsync() 43 { 44 return (await this.SaveChangesAsync()) > 0; 45 } 46 47 public void Add<TEntity>(TEntity entity) where TEntity : class 48 { 49 this.Set<TEntity>().Add(entity); 50 } 51 52 public void Update<TEntity>(TEntity entity) where TEntity : class 53 { 54 this.Entry(entity).State = EntityState.Modified; 55 } 56 57 public void Remove<TEntity>(TEntity entity) where TEntity : class 58 { 59 this.Entry(entity).State = EntityState.Deleted; 60 } 61 }
這。寫着寫着本身都有點不知所云了,但願對正在學習階段的朋友有一點點幫助!