您正在查看通常似乎实现的存储库模式:
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);
当然这是一种更好的方法吗?我错过了什么吗?它自动也只有一个上下文。
答案 0 :(得分:6)
存储库模式不会将数据访问与数据存储分离,这就是NHIBnate或Enity Framework等ETL工具所做的事情。存储库模式提供了可重用的数据提取方法。
我以前使用过你所描述的所谓“通用”存储库,并认为它很棒。直到你意识到你刚刚在NHibernate或实体框架之上放置了另一层,你才意识到它已经全部消失了Pete Tong。
理想情况下,您需要的是描述从数据存储中获取数据的方式的接口,并且不应泄漏您正在使用的数据访问。例如:
public interface IEmployee interface
{
IEmployee GetEmployeeById(Guid employeeId);
IEmployee GetEmployeeByEmployeeNumber(string employeeNumber);
IEnumerable<IEmployee> GetAllEmployeesWithSurname(string surname);
IEnumerable<IEmployee> GetAllEmployeesWithStartDateBetween(DateTime beginDateTime, DateTime endDateTime);
}
这为您提供了代码合同,不知道您的持久层,并且用于检索数据的查询可以单独进行单元测试。接口可以从提供常见CRUD方法的基接口继承,但您可以假设所有存储库都需要CRUD。
如果您沿着Generic Repository的路走下去,最终会在查询中出现重复,您会发现使用存储库的代码进行单元测试要困难得多,因为您还必须测试查询。 / p>
答案 1 :(得分:1)
泛型本身并不构成存储库模式的实现。我们都看到了在示例存储库模式实现中使用的通用基类,但这是通过从基类(在您的情况下为GenericRepository
)继承到更专业化来使事情干(不要重复自己)儿童班。
仅使用泛型基类GenericRepository
假定您的存储库只需要最基本的CRUD方法。对于更复杂的系统,每个存储库基于底层业务实体数据要求变得更加专业化。
此外,您还需要具有与其他图层定义数据合同的接口。使用存储库模式意味着您不希望将存储库的具体实现公开给其他层。