存储库模式+工作单元

时间:2012-12-04 03:00:06

标签: model-view-controller design-patterns repository unit-of-work

经过近一年的时间,我正在开始一个新的mvc项目,这次是版本4.我想知道下面的存储库模式实现是否有更多的缺点而不是优点。

public interface IRepository<T> where T : class
{
    IEnumerable<T> GetAll();

    IQueryable<T> Query(Expression<Func<T, bool>> filter);

    void Add(T entity);

    void Remove(T entity);
}

public interface IUnitOfWork
{
    void Commit();
}

public interface IDbContext : IDisposable
{
    IDbSet<T> Set<T>() where T : class;

    int SaveChanges();
}

public class DbContextAdapter : IDbContext
{
    private readonly DbContext _myRealContext;

    public DbContextAdapter()
    {
        this._myRealContext = new EstafaContext();
    }

    public void Dispose()
    {
        _myRealContext.Dispose();
    }

    public IDbSet<T> Set<T>() where T : class
    {
        return _myRealContext.Set<T>();
    }

    public int SaveChanges()
    {
        return _myRealContext.SaveChanges();
    }
}

public class SqlRepository<T> : IRepository<T> where T : class
{
    private IDbSet<T> _dbSet;

    public SqlRepository(IDbContext dbContext)
    {
        this._dbSet = dbContext.Set<T>();
    }

    public IEnumerable<T> GetAll()
    {
        return this._dbSet.ToList();
    }

    public IQueryable<T> Query(Expression<Func<T, bool>> filter)
    {
        return this._dbSet.Where(filter);
    }

    public void Add(T entity)
    {
        this._dbSet.Add(entity);
    }

    public void Remove(T entity)
    {
        this._dbSet.Remove(entity);
    }
}

public class SqlUnitOfWork : IDisposable, IUnitOfWork
{
    private IDbContext _dbContext;

    private SqlRepository<Cliente> _clientes ;

    public SqlUnitOfWork()
    {
        this._dbContext = new DbContextAdapter();
    }

    public void Dispose()
    {
        if (this._dbContext != null)
        {
            this._dbContext.Dispose();
        }
        GC.SuppressFinalize(this);
    }

    public IRepository<Cliente> Clientes
    {
        get { return _clientes ?? (_clientes = new SqlRepository<Cliente>(_dbContext)); }
    }       

    public void Commit()
    {
        this._dbContext.SaveChanges();
    }
}

这样我就可以通过SqlUnitOfWork从一个点管理所有存储库。 我在之前的项目中使用了这个设计并且工作得很好,但我觉得它效率不高而且可能多余。 是否值得添加这样一个抽象层?

提前致谢!

2 个答案:

答案 0 :(得分:1)

虽然我的实现并不完全像你所拥有的那样,但对我来说似乎非常可靠。

我通常做的唯一其他更改是为每个实体类型存储库定义特定接口,如下所示:

public interface IClienteRepository : IRepository<Cliente>
{
  IEnumerable<Cliente> GetByName(string firstName);
  // etc
}

这样我仍然可以将所有存储库一般用于我的CRUD操作,但我也可以使用相同的存储库来抽象出一些查询逻辑。您的存储库用户应该只知道他们想要什么,而不是如何获得它。

当然,这有点单调乏味,要求您对存储库进行具体实现以增加额外的功能,但它只是封装了您在其他地方通过应用程序获得的查询逻辑。

答案 1 :(得分:1)

我不知道它是否有更多的缺点或优点,但多年来,我发现这种类型的存储库模式越来越没用。除非实时切换数据库或数据源,或者如果你需要一些疯狂的模拟宇宙测试覆盖率,我认为它比它的价值更麻烦。

仅仅是我个人的偏好,但我更喜欢我的数据访问方法。例如,如果我将模型返回到视图,它们肯定会与我的数据库中的表看起来不同。所以我想要一个GetAllModelX方法,而不是GetAllDbTableRows方法。

那么这个转换代码将被安置在哪里?在控制器?另一个将实体转换为模型的数据访问层?甚至有正确或错误的答案?可能不是。

我在这里肯定会扮演魔鬼的拥护者,但根据我的经验,我已经摆脱了这种通用的存储库设计,转而支持返回/接受模型的数据访问层,并且通常使用EF处理针对数据库的所有查询/ CRUDding / UnitOfWork。但话说回来,我是一位经典的单元测试人员,他没有做太多的嘲弄,也做了更多的集成测试。