前言
對於倉儲Repository的設計,其實很多人都很糾結,因為從廣義來說,Repository有兩種類型:
IRepository和IRepository<T>
框架的重構想得最多的最重要的幾個問題:
1:解耦(每層可以替換其他的,比如換一個UI層可以把Web 項目快速轉換成Winform項目)
2:擴展性(可以靈活抹去框架的某個層,讓其他的第三方框架依據自己的接口實現該層的邏輯,其它層不變,也就是插拔式擴展)
3:靈活(開發便捷,使用靈活)
4:維護性(別人了解框架后,可以讓別人無障礙維護)
........
-------------------------------------
題外話不多說 馬上進入辯證主題:是IRepository還是IRepository<T> ?
------------------------------------
首先看IRepository<T>
IRepository<T>接口定義形式如下(其中IEntity是一個實體類接口):
1 public interface IRepository<T> where T : Entity.IEntity 2 { 3 T FindBy(string primaryKey); 4 IEnumerable<T> FindAll(); 5 IEnumerable<T> FindAll(string where); 6 IEnumerable<T> FindAll(string where, string order); 7 IEnumerable<T> FindAll(int pageIndex, int pageSize, string where, string order, out int count); 8 void Add(T entity); 9 void Delete(T entity); 10 void DeleteAll(); 11 void DeleteAll(string where); 12 void DeleteAll(System.Collections.IEnumerable pkValues); 13 void Update(T entity); 14 bool Exists(string primaryKey); 15 }
可以看見,IRepository和接口IEntity通過泛型T結合在了一起,形成了耦合
IRepository<T> 可以通過T操作IEntity
開發的時候,每個IEntity的子類都得對應一個IRepository<T>的子類,如:
public class DepartmentRepository : Repository.RepositoryBase<Entity.Department.Department> { }
其中Department是IEntity的一個子類
而RepositoryBase<T>是一個真正可用的倉儲父類(此類已通過第三方或者自己的ORM框架實現了數據庫操作)
------------------------------------
再看IRepository接口
------------------------------------
IRepository接口的設計:
public interface IRepository { #region 實體相關接口 TEntity FindBy<TEntity>(IEnumerable<string> primaryKey) where TEntity : IEntity; IEnumerable<TEntity> FindAll<TEntity>() where TEntity : IEntity; IEnumerable<TEntity> FindAll<TEntity>(string where, params System.Data.IDataParameter[] ps) where TEntity : IEntity; IEnumerable<TEntity> FindAll<TEntity>(string where, string order, params System.Data.IDataParameter[] ps) where TEntity : IEntity; IEnumerable<TEntity> FindAll<TEntity>(int pageIndex, int pageSize, string where, string order, out int count, params System.Data.IDataParameter[] ps) where TEntity : IEntity; void Add<TEntity>(TEntity entity) where TEntity : IEntity; void Delete<TEntity>(TEntity entity) where TEntity : IEntity; void DeleteAll<TEntity>() where TEntity : IEntity; void DeleteAll<TEntity>(string where, params System.Data.IDataParameter[] ps) where TEntity : IEntity; void DeleteAll<TEntity>(IEnumerable<IEnumerable<string>> pkValues) where TEntity : IEntity; void Update<TEntity>(TEntity entity) where TEntity : IEntity; bool Exists<TEntity>(IEnumerable<string> primaryKey) where TEntity : IEntity; #endregion #region 原始數據操作接口 int ExecuteSql(string sql, params System.Data.IDataParameter[] ps); object ExecuteScalar(string sql, params System.Data.IDataParameter[] ps); System.Data.DataTable ExecuteDataTable(string sql, params System.Data.IDataParameter[] ps); #endregion }
這種接口的設計就是把IReopository<T>里的T放入接口的方法中,
讓泛型方法操作對應的帶入泛型實體類
IReopository接口的設計可以很好地實現Repository共用
也就是說整個項目只要一個通過ORM實現了的RepositoryBase類就可以操作所有的持久層實體對象
不用每個實體類都對應一個Repository
大大的減少了項目開發的繁雜性
對於業務邏輯,新增一個Server層讓每個Server類對應一個實體類的邏輯
如:假設有Class Aa 則必須有 Class AaServer對應
而Server就調用RepositoryBase類操作Server類對應的實體
--------------------------------------
總結:
其實不管是IRepository還是IRepository<T> 都各自有各自的優勢:
1、IRepository<T>的子類對實體類是很專注的,它只可以操作一個實體類,對IRepository<T>的子類的修改不會影響到其他實體類的操作
從而可以實現對應實體類的個性化拓展;
2、IRepository可以操作所有的實體類,修改IRepository的子類則會影響所有的實體的操作
雖然如此,在開發過程中,難免會有在某個業務層XxServer操作其他實體類的需要
如果是用IRepository<T>倉儲,那么必須在業務層XxServer中New很多其他實體類對應的IRepository<T>的子類對象出來
這對於Repository與Server的解耦是個大忌,也就是說Repository層和Server層已經高度耦合了。
也正因為這個原因我個人更傾向於IRepository,並拋棄Repository層(如果是每個實體對應一個Repository,那么將需要一個Repository層),
只讓一個可以操作所有所有實體的Repository存在就可以了
更重要的原因是Repository層相對來說,接口比較穩定,一般的項目,沒有要擴展IRepository接口操作的需要。
所以IRepository接口一個重要的優勢是:
在某個實體類的Server層可以統一用IRepository類的方法實現業務,
不需要像IRepository<T>實現方式一樣,New額外的對象就才可以操作其他實體類,
只要在【Repository.方法<T>】里的T換成其他實體類就可以了
這對解耦來說是有好處的。
所以正是因為這個原因,我選擇IRepository,而不是IRepository<T>
---------------------
題外話
上面的IRepository接口已經被我再次拋棄了
拋棄原因如下:
1:接口的組合主鍵擴展性差,也就是說主鍵會受制於ORM框架的實現
2:不支持搜索和排序解耦
至於新的IRepository接口 將在下篇文章給出
-------------------------------------
完