Asp.net-Mvc
每種實現的儲存庫模式優缺點
嗨,看看通常似乎實現如下的儲存庫模式:
public class GenericRepository<TEntity> where TEntity : class { // other business public virtual TEntity GetByID(object id) { return db.Set().Find(id); } public virtual void Insert(TEntity entity) { db.Set().Add(entity); } public virtual void Delete(object id) { TEntity entityToDelete = db.Set().Find(id); Delete(entityToDelete); } public virtual void Update(TEntity entityToUpdate) { db.Set().Attach(entityToUpdate); context.Entry(entityToUpdate).State = EntityState.Modified; } }因此,對於您想要使用的每種類型(即更新),您需要實例化一個儲存庫。
因此,如果我有兩種我想保存的類型
Cars,Trucks我需要去:var carRepository = new GernericRepository<Car>(); carRepository.Update(myCar); var truckRepository = new GernericRepository<Truck>(); carRepository.Update(myTruck);因此,您對每種類型都有單獨的儲存庫。為了確保您一次保存所有內容,您需要
unitOfWork確保它們都使用相同的上下文並一次保存。擁有類似的東西肯定不是更好:
public class GenericRepository { // other business public virtual TEntity GetByID<TEntity>(object id) where TEntity : class { return db.Set<TEntity>().Find(id); } public virtual void Insert<TEntity>(TEntity entity) where TEntity : class { db.Set<TEntity>().Add(entity); } public virtual void Delete<TEntity>(object id) where TEntity : class { TEntity entityToDelete = db.Set<TEntity>().Find(id); Delete(entityToDelete); } public virtual void Update<TEntity>(TEntity entityToUpdate) where TEntity : class { db.Set<TEntity>().Attach(entityToUpdate); context.Entry(entityToUpdate).State = EntityState.Modified; } }這意味著儲存庫只需要實例化一次,因此真的是通用的嗎?
所以你可以像這樣更新你的汽車和卡車:
var repository = new GernericRepository<Car>(); repository.Update<Car>(myCar); rRepository.Update<Truck>(myTruck);當然這是一個更好的方法?我錯過了什麼嗎?它也自動只有一個上下文。
儲存庫模式不會將數據訪問與數據儲存分離,這正是 NHibernate 或 Enity Framework 等 ETL 工具所做的事情。儲存庫模式為提取數據提供了可重用的方法。
正如您所描述的那樣,我以前使用過一個所謂的“通用”儲存庫,並認為它很棒。直到您意識到您剛剛在 NHibernate 或實體框架之上添加了另一層,您才意識到這一切都消失了 Pete Tong。
理想情況下,您需要的是描述從數據儲存中獲取數據的方式的介面,並且不應該洩露您正在使用的數據訪問權限。例如:
public interface IEmployee { IEmployee GetEmployeeById(Guid employeeId); IEmployee GetEmployeeByEmployeeNumber(string employeeNumber); IEnumerable<IEmployee> GetAllEmployeesWithSurname(string surname); IEnumerable<IEmployee> GetAllEmployeesWithStartDateBetween(DateTime beginDateTime, DateTime endDateTime); }這為您提供了一個程式碼契約,不了解您的持久層,並且用於檢索數據的查詢可以單獨進行單元測試。該介面可以從提供通用 CRUD 方法的基本介面繼承,但您會假設您的所有儲存庫都需要 CRUD。
如果您走通用儲存庫的道路,您最終會在查詢中出現重複,並且您會發現對使用儲存庫的程式碼進行單元測試要困難得多,因為您還必須測試查詢。