DDD存储库中的过滤器

时间:2011-08-07 19:53:23

标签: domain-driven-design

有Campaign Entity,为此,我有CampaignRepository,它有这个功能

  1. public IList FindAll();
  2. 公共广告系列FindByCampaignNumber(字符串编号);
  3. 但现在我想要这个标准 - :

    1. 查找今天创建的广告系列。
    2. 查找本月创建的广告系列
    3. 查找前5个最新广告系列。
    4. 查找今年创建的广告系列。
    5. 因此,对于所有这些广告系列过滤器,

      我是否在存储库中为每个人创建了单独的功能?

      并以这种方式实施。

      Getall广告系列然后过滤所需的广告系列,但我不想要所有广告系列。在谷歌搜索时,我找到了这个解决方案

      1:http://russelleast.wordpress.com/2008/09/20/implementing-the-repository-and-finder-patterns/

      有什么方法我可以避免多个功能,还是继续为每个过滤器创建单独的功能?

4 个答案:

答案 0 :(得分:8)

您是否考虑在应用中实施Specification模式?也许它看起来像是一种矫枉过正,但如果你的应用程序有一些复杂的用户过滤选项,它可能会很有用。

class CampaignSpecification
{
    public CampaignSpecification Number(string number);
    public CampaignSpecification DateBetween(DateTime from, date to);
    public CampaignSpecification Year(DateTime year);
} //I have omitted all the AND/OR stuff it can be easily implemented with any SQL like query language

以下是从存储库加载的方式如何

的示例
var  campaignList = CampaignRepository.load(
            new CampaignSpec()
                .Number("2")
                .Year(DateTime.Now);

此外,我想补充一点,它在很大程度上取决于您使用的是哪种数据访问解决方案,当您知道将使用哪种API时,它会使实现变得更容易(Criteria API,SQL或其他),所以你可以调整您的规范界面,使其实现更简单。

UPDATE :如果您使用linq和nHibernate在.NET中实现规范,请查看http://linqspecs.codeplex.com/

答案 1 :(得分:3)

我会创建两个规范:TopCampaignSpec和CampaingCreatedSpec。

var spec = CampaignCreatedSpec.ThisYear();
var campaigns = CampaignsRepository.FindSatisfying(spec);

如果您在其他地方需要此功能,还可以使用更通用的DateRange类替换CampaingCreatedSpec:

var thisYear = DateRange.ThisYear();
var campaigns = CampaignsRepository.FindByDateRange(spec);

我还强烈建议远离'通用'存储库和实体。请阅读this

从DDD的角度来看,数据访问代码是实现为SQL / HQL / ICriteria还是Web服务调用并不重要。此代码属于存储库实现(数据访问层)。这只是一个样本:

public IList<Campaign> FindByDateRange(CampaignCreatedSpec spec) {
    ICriteria c = _nhibernateSession.CreateCriteria(typeof(Campaign));
    c.Add(Restrictions.Between("_creationDate", spec.StartDate, spec.EndDate));
    return c.List<Campaign>();
}

答案 2 :(得分:2)

我将如何做到这一点:

class Campaigns{
  IEnumerable<Campaign> All(){...}
  IEnumerable<Campaign> ByNumber(int number){...}
  IEnumerable<Campaign> CreatedToday(){...}
  IEnumerable<Campaign> CreatedThisMonth(){...}
  IEnumerable<Campaign> CreatedThisYear(){...}
  IEnumerable<Campaign> Latest5(){...}

  private IQueryable<Campaign> GetSomething(Something something){
    //used by public methods to dry out repository
  }
}

推理很简单 - 重要的是您有兴趣寻找广告系列(知识是您网域的一部分)。如果我们明确说明函数来反映这一点,我们将始终知道它。


  

在广告系列资源库中添加所有这些方法是否合适?

我没有看到任何错误。

  

Arnis我想要一些代码,你如何在域中实现Created today功能,你是否在这个函数中注入了存储库?谢谢你的合作

我不会在我的域中实现CreatedToday函数。它将位于存储库中,存储库实现不应该涉及域。如果您的意思是我将如何使用Campaign存储库以及是否应该从域中使用它 - 否,则不应在域内使用它。如果你的意思是我是否会在存储库中注入存储库 - 你正在倾听xzibit

答案 3 :(得分:-1)

您应该能够使用以下存储库方法执行上述所有操作:

List<Campaign> findCampaigns(Date fromCreationDate, Date toCreationDate, int offset, Integer limit) {

   if (fromCreationDate != null) add criteria...
   if (toCreationDate != null) add criteria...
   if (limit != null) add limit...
}

我就是这样做的,效果非常好。