每个实现的存储库模式的优缺点



嗨,看看仓库模式,它通常是这样实现的:

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;
    }
}

所以对于你想要使用的每种类型(例如更新),你都需要实例化一个存储库。

如果我有两种类型我想保存CarsTrucks我需要输入

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);

这肯定是一个更好的方法吗?我错过什么了吗?它也自动只有一个上下文

存储库模式不会将数据访问与数据存储解耦,这是ETL工具(如NHibernate或entity Framework)所做的。存储库模式为提取数据提供了可重用的方法。

我以前使用过所谓的"通用";仓库,如你所描述的,并认为它是伟大的。直到你意识到你刚刚在NHibernate或实体框架上放了另一层,你才意识到它都消失了。

理想情况下,您想要的是描述从数据存储中获取数据的方法的接口,并且不应该泄漏您正在使用的数据访问。例如:

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。

如果你沿着通用存储库的道路走下去,你最终会在查询中重复,你会发现更难对使用存储库的代码进行单元测试,因为你也必须测试查询。

泛型本身并不能实现存储库模式。我们都看到了在示例存储库模式实现中使用的泛型基类,但这是为了通过从基类(在您的示例中为GenericRepository)继承到更专门的子类来使事情DRY(不要重复自己)。

仅使用泛型基类GenericRepository就假定您的存储库只需要最基本的CRUD方法。对于更复杂的系统,每个存储库根据底层业务实体数据需求变得更加专门化。

此外,您还需要有接口来定义与其他层之间的数据契约。使用存储库模式意味着您不希望将存储库的具体实现暴露给其他层。

最新更新