我有一个存储库类。我想向此类添加分页,搜索和排序。我该怎么办?
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();
}
}
答案 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或什至是文件系统!)
请不要在此处使用存储库模式。就像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来实现,则实现易于创建,测试和使用的,集中的,表达性的存储库变得轻而易举。