简体   繁体   English

如何通过存储库模式执行聚合操作?

[英]How can I perform aggregate operations via the repository pattern?

I've seen various blog posts (and much conflicting advice) about the repository pattern, and so I'll start by saying that the code below is probably not following the repository pattern in many people's opinion. 我已经看过关于存储库模式的各种博客文章(以及很多相互矛盾的建议),所以我首先要说的是,下面的代码可能不是很多人认为的存储库模式。 However, it's a common-enough implementation, and whether it adheres to Fowler's original definition or not, I'm still interested in understanding more about how this implementation is used in practice. 然而,这是一个通用的实现,并且它是否遵循福勒的原始定义,我仍然有兴趣了解更多关于如何在实践中使用该实现。

Suppose I have a project where data access is abstracted via an interface such as the one below, which provides basic CRUD operations. 假设我有一个项目,通过下面的接口抽象数据访问,这个接口提供基本的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);
}

Further suppose that I have a service layer built atop that, for example: 进一步假设我在其上构建了一个服务层,例如:

public class FooService
{
    private IGenericRepository<Foo> _fooRespository;

    ...

    public IEnumerable<Foo> GetBrightlyColoredFoos()
    {
        return _fooRepository.Fetch(f => f.Color == "pink" || f.Color == "yellow");
    }
}

Now suppose that I now need to know how many brightly colored Foo s there are, without actually wanting to enumerate them. 现在假设我现在需要知道有多少颜色鲜艳的Foo ,而实际上并不想要枚举它们。 Ideally, I want to implement a CountBrightlyColoredFoos() method in my service, but the repository implementation gives me no way to achieve that other than by fetching them all and counting them - which is potentially very inefficient. 理想情况下,我想在我的服务中实现CountBrightlyColoredFoos()方法,但是存储库实现让我无法实现除了通过获取它们并计算它们之外的其他方法 - 这可能是非常低效的。

I could extend the repository to add a Count() method, but what about other aggregate functions that I might need, such as Min() or Max() , or Sum() , or... you get the idea. 我可以扩展存储库以添加Count()方法,但是我可能需要的其他聚合函数如Min()Max() ,或Sum() ,或者......你得到了这个想法。

Likewise, what if I wanted to get a list of the distinct Foo colors ( SELECT DISTINCT ). 同样,如果我想获得不同Foo颜色的列表( SELECT DISTINCT ),该怎么办? Again, the simple repository provides no way to do that sort of thing either. 同样,简单的存储库也无法做到这一点。

Keeping the repository simple to make it easy to test/mock is very laudable, but how do you then address these requirements? 保持存储库简单以便于测试/模拟是非常值得称赞的,但是您如何解决这些需求呢? Surely there are only two ways to go - a more complex repository, or a "back-door" for the service layer to use that bypasses the repository (and thus defeats its purpose). 当然,只有两种方法可以实现 - 更复杂的存储库,或者服务层使用的“后门”绕过存储库(因此无法实现其目的)。

I would say you need to change your design. 我会说你需要改变你的设计。 What you want to do is have one "main" generic repository that has your basic CRUD, but also smaller repositories for each entity. 你想要做的是有一个“主”通用存储库,它有你的基本CRUD,但每个实体也有一个较小的存储库。 You will then just have to draw a line on where to place certain operations (like sum, count, max, etc.) Most likely not all your entities are going to have to get counted, summed, etc. and most of the time you won't be able to add a generic version that applies to all entities for aggregate functions. 然后,您只需要在某处操作(如总和,计数,最大等)放置一条线。很可能并非所有实体都必须计算,求和等等。大多数时候你将无法添加适用于聚合函数的所有实体的通用版本。

Base Repository: 基础知识库:

public abstract class BaseRep<T> : IBaseRep<T> where T : class
{
   //basic CRUD
}

Foo Repository: Foo存储库:

public class FooRep : BaseRep<Foo>, IFooRep
{
   //foo specific functions
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM