3

我正在为我的应用程序开发一个通用存储库,我在这里有一些疑问。

这是我为通用存储库提供的一些代码:

public interface IEntityRepository<T> where T : class
{
    void Add(T entity);
    T GetById(int id);
    IEnumerable<T> Get(Expression<Func<T, bool>> predicate);
    IEnumerable<T> GetAll();
}

public class EntityRepository<T> : IDisposable, IEntityRepository<T> where T : class
{
    protected DbSet<T> DbSet;
    protected DbContext Context;

    public EntityRepository(DbContext dataContext)
    {
        DbSet = dataContext.Set<T>();
        Context = dataContext;
    }

    public void Add(T entity)
    {
        DbSet.Add(entity);
    }

    public IEnumerable<T> Get(Expression<Func<T, bool>> predicate)
    {
        return DbSet.Where(predicate);
    }

    public IEnumerable<T> GetAll()
    {
        return DbSet;
    }

    public T GetById(int id)
    {
        return DbSet.Find(id);
    }

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

我遇到的困难是:

1 - 我应该将 IEnumerable 从存储库层返回到服务层而不是 IQueryable 吗?我在网上阅读了一些关于这个主题的文章,但找不到一个明确的 - 或相当明确的 - 回答这个问题。通过返回 IEnumerable,所有后续查询都将在本地完成,对吗?

2 - 显然需要的一件事是能够检索分页数据。我不想仅仅为了显示 50 条记录而获得 100,000 条记录。我的问题是,这个“逻辑”是否应该在存储库或服务中,即服务获取所有数据,然后根据需要跳过/获取或存储库已经只返回服务需要的数据?或者这些类型的方法应该在继承通用方法的特定存储库中?

提前致谢

4

1 回答 1

1

永远不要返回 IQueryable,因为它是 ORM 的一个实现细节并且违背了使用存储库的精神:告诉存储库你想要什么,而不是如何。IQueryable 意味着您正在自己构建查询的一部分,因此您告诉它如何

通用存储库主要是一种反模式,因为它使用ORM 实体而不是域实体。即使使用域实体,它也只能用作域存储库,因为您需要不同的接口定义来进行查询。根据需要定义每个存储库接口。

关于分页,只需将 'skip' 和 'take' 参数传递给 repo 方法。即使您不使用 ORM,它也可以工作,repo 将根据它用于与 db 一起工作的 DAO 实现分页。为了您自己的利益,请尝试采用 CQRS 思维方式,这将使您的 DDD 生活更轻松。

于 2013-11-01T09:07:41.140 回答