我见过关于存储库模式的各种博客帖子(以及许多相互矛盾的建议),所以我首先要说的是,很多人认为下面的代码很可能是而不是。然而,这是一个通用的实现,并且它是否遵守Fowler的原始定义,我仍然有兴趣了解更多关于这个实现如何在实践中使用的知识。如何通过存储库模式执行聚合操作?
假设我有一个项目,通过一个接口抽象数据访问,如下面的接口,它提供了基本的CRUD操作。
public interface IGenericRepository<T>
{
void Add(T entity);
void Remove(T entity);
void Update(T entity);
IEnumerable<T> Fetch(Expression<Func<T,bool>> where);
}
进一步假设我有之上构建一个服务层,例如:
public class FooService
{
private IGenericRepository<Foo> _fooRespository;
...
public IEnumerable<Foo> GetBrightlyColoredFoos()
{
return _fooRepository.Fetch(f => f.Color == "pink" || f.Color == "yellow");
}
}
现在假设我现在需要知道多少鲜艳Foo
那儿是不实际想要列举它们。理想情况下,我想在我的服务中实现一个CountBrightlyColoredFoos()
方法,但是存储库实现让我无法实现这一点,除非将它们全部提取并计数 - 这可能非常低效。
我可以扩展存储库添加Count()
方法,但怎么样,我可能需要其他的聚合函数,如Min()
或Max()
,或Sum()
,还是......你的想法。
同样,如果我想获得不同的Foo颜色列表(SELECT DISTINCT
),该怎么办。同样,简单的存储库也没有办法做这种事情。
保持资源库简单以便于测试/模拟是非常值得赞赏的,但您如何解决这些需求?当然,只有两种方式可以使用 - 一个更复杂的存储库,或者服务层使用的绕过存储库的“后门”(从而破坏其目的)。
能IEnumerable的''是一个IQueryable的''这里,用适当的LINQ提供程序?如果可能,这将是更可取的,因为它提供了解决'IEnumerable '提取方法限制的机会。 –
我想,只要服务层方法返回'IEnumerable',那么库层就可以使用'IQueryable'。我知道这只是一种双向的想法,但我确实喜欢IEnumerable的简单性(特别是测试)... –
总是有'公共静态的IQueryable AsQueryable已(这IEnumerable的源)'进行单元测试目的返回一个存根'的IEnumerable '作为'IQueryable的' –