分页,排序和搜索在哪里进入存储库模式?

时间:2018-08-05 07:59:43

标签: c# repository-pattern

我有一个存储库类。我想向此类添加分页,搜索和排序。我该怎么办?

 public class Repository<T> : IRepository<T> where T : class
    {
        private readonly DatabaseContext _context = new DatabaseContext();

        public IQueryable<T> GetAll(params Expression<Func<T, object>>[] includeProperties)
        {
            IQueryable<T> dbQuery = _context.Set<T>();
            dbQuery = includeProperties.Aggregate(dbQuery, (current, includeProperty) => current.Include(includeProperty));
            return dbQuery.AsNoTracking().AsQueryable();
        }
}

2 个答案:

答案 0 :(得分:3)

与问题直接相关的有根据的答案

关于.NET和存储库模式,通常尝试使您的方法返回IQueryable。这使您可以“链接” linq查询,然后可以链接常用的表达式,例如分页和排序。这意味着您可以越来越多地重用这些方法,并避免编写一两次会使用的自定义方法堆。这种情况的例外(总是有例外,对吧?)是当您需要达到某些特定的性能指标时(例如,此代码需要运行FAST,因此数据库查询需要快速/特定)。

在上面的代码示例中,您已开始执行此操作:

public IQueryable<T> GetAll(params Expression<Func<T, object>>[] includeProperties) { .. }

这使您可以将GetAll方法重用于其他各种用途。分页?当然。订购吗?好的..让我们也订购。实际上,您可以使用在IQueryable中找到的所有常规linq扩展名,并且可以根据所使用的基础存储库适当地过滤结果。

通常,这意味着您的方法将最终进行数据库调用,然后结果将由链式方法进一步处理,但这再次取决于您在GetAll方法中的实现。

因此,总而言之->在存储库模式方法中不要进行分页/排序/聚合,这是一般规则,因为这将导致重复使用率较高且硬编码较少的方法。

另一方面,如果要使用与性能相关的特定指标,则应该有一些包括排序或分页的特定方法。例如,您可能想查询特定的存储过程或自定义Sql查询或自定义DocumentDB索引(是的,除了Microsoft Sql Server之类的关系数据库外,存储库模式还可以用于其他存储库。它可以用于DocDb或什至是文件系统!)

关于.NET + EF +存储库模式的有根据的答案

请不要在此处使用存储库模式。就像OP中提到的一些评论一样,如果您使用的是EF,那么 实际上是一个存储库模式,并且已经完成了一个工作单元。在过去,人们由于在BadOldDays(tm)..中EF的失败而在EF上添加了自己的存储库模式。

我们都前进了。 EF已经成熟(据说)。您现在真的不需要这样做。

哦-您正在执行存储库模式的机率通常是99%,因为“您将来可能会切换数据库”。人们很少会关闭数据库,如果他们最终这样做了……他们通常会有更多的问题,希望他们使用存储库模式。

最后,在某些情况下,“存储库模式”是有利的,但没有任何IMO声明暗示可能是这种情况,因此,我假设情况并非如此。提示:像脱机移动设备这样的应用程序,每个移动应用程序OS可能使用不同的数据库。

最后通知

作为答案,整个答案几乎可以辩论。当使用Repository Pattern + .NET时,有一些 general 建议(即我的答案的前半部分),但是在答案的后半部分中,我们总是有意见。所以...祝你好运!

答案 1 :(得分:3)

我将建议一些与已经存在的答案和评论不同的东西。您不是在尝试填充所有数据访问用例的通用存储库,而是创建了不同的存储库,这些存储库的设计由您的域需求决定。

IMO,通用存储库导致的问题超出了解决的范围:

  • 如果一个实体不需要删除功能怎么办?
  • 如果一个实体不需要GetAll方法怎么办?
  • IQueryable<T>是一个泄漏的抽象

通用存储库只会使您的设计难于发展,因为最终您必须在任何给定情况下都必须实现所有这些方法,无论实际要求是什么,人们仍然可以严重依赖返回的{{1} }导致查询层之间的逻辑泄漏。

相反,您可以轻松地执行以下操作:

IQueryable<T>

一旦有了这样的一些存储库,创建其他存储库的成本就会大大降低。尤其是如果您使用Dapper之类的东西并使用Dapper.Contrib来实现,则实现易于创建,测试和使用的,集中的,表达性的存储库变得轻而易举。