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

Ano*_*use 8 asp.net-mvc repository-pattern

嗨,看看通常似乎实现的存储库模式,如:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,对于您要使用的每种类型(即更新),您需要实例化存储库.

所以如果我有两种类型我想保存Cars,Trucks我需要去:

var carRepository = new GernericRepository<Car>();
carRepository.Update(myCar);

var truckRepository = new GernericRepository<Truck>();
carRepository.Update(myTruck);
Run Code Online (Sandbox Code Playgroud)

那么你就为每种类型都有单独的存储库.要确保一次保存所有内容,您需要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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这意味着存储库只需要实例化一次,因此是真正的通用?

所以你可以更新你的汽车和卡车:

var repository = new GernericRepository<Car>();
repository.Update<Car>(myCar);
rRepository.Update<Truck>(myTruck);
Run Code Online (Sandbox Code Playgroud)

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

Bro*_*ski 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);
}
Run Code Online (Sandbox Code Playgroud)

这为您提供了代码合同,您不了解持久层,并且用于检索数据的查询可以单独进行单元测试.接口可以从提供常见CRUD方法的基接口继承,但您可以假设所有存储库都需要CRUD.

如果你走在通用存储库的道路上,你最终会在查询中出现重复,你会发现使用存储库的代码进行单元测试要困难得多,因为你也必须测试查询.

  • @Bronumski:根据定义,存储库模式**确实将数据存储(数据的物理位置)与数据访问(用于与该数据交互的方法)分离.EF和NHibernate提供了将应用程序与其技术紧密结合的存储库实现,因此您可以创建自己的存储库包装器,从而将任何特定技术的使用与应用程序分离.更复杂的场景将存储库概念分解为一组服务层,允许存储库概念专注于构建查询而不是返回特定数据集. (3认同)