Фильтры в репозитории DDD - PullRequest
       3

Фильтры в репозитории DDD

9 голосов
/ 07 августа 2011

Существует объект Campaign, и для этого у меня есть CampaignRepository, у которого есть эти функции

  1. public IList FindAll ();
  2. public Campaign FindByCampaignNumber (номер строки);

Но теперь мне нужны эти критерии -:

  1. Поиск кампаний, созданных сегодня.
  2. Поиск кампаний, созданных в этом месяце
  3. Найдите топ-5 последних кампаний.
  4. Найдите кампании, созданные в этом году.

Таким образом, для всех фильтров этих кампаний

Создаю ли я отдельнофункционировать для каждого из них в репозитории?

и реализовать таким образом.

Кампании Getall и затем отфильтровывать требуемые кампании, но я не хочу все кампании.При поиске в Google я нахожу это решение

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

Есть ли какой-либо метод, который я могу избежать нескольких функций или я иду вперед и создать отдельные функции для каждого из этогофильтр?

Ответы [ 4 ]

8 голосов
/ 08 августа 2011

Рассматривали ли вы применение шаблона Спецификация в своем приложении?Возможно, это выглядит излишним, но может оказаться полезным, если ваше приложение будет иметь несколько сложных пользовательских фильтров.

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 или любой другой), так что выможно настроить интерфейс спецификаций, чтобы упростить его реализацию.

ОБНОВЛЕНИЕ : если вы реализуете спецификации в .NET с использованием linq и nHibernate, ознакомьтесь с http://linqspecs.codeplex.com/

3 голосов
/ 08 августа 2011

Я бы пошел с созданием двух спецификаций: TopCampaignSpec и CampaingCreatedSpec.

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

CampaingCreatedSpec также можно заменить более универсальным классом DateRange, если вам нужна эта функция в другом месте:

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

Я также настоятельно рекомендую держаться подальше от «общих» репозиториев и сущностей.Пожалуйста, прочитайте this

С точки зрения DDD не имеет значения, реализован ли код доступа к данным как SQL / HQL / ICriteria или даже вызов веб-службы.Этот код относится к реализации репозитория (уровень доступа к данным).Это всего лишь пример:

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 голосов
/ 08 августа 2011

Вот как бы я это сделал:

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
  }
}

Рассуждение простое - оно имеет значение в зависимости от того, что Вас интересует для поиска кампаний (эти знания являются частью Вашего домена). Если мы будем явно указывать функции, отражающие это, мы всегда будем знать это.


Уместно ли добавить все эти методы в репозиторий кампании?

Я не вижу в этом ничего плохого.

Арнис, я хочу немного кода, как вы реализуете созданную сегодня функцию в самом домене, вы внедряете репозиторий здесь, в этой функции? Спасибо за ваше сотрудничество

Я бы не реализовал функцию CreatedToday в моем домене. Он будет находиться в репозитории, и реализация репозитория не должна касаться домена. Если Вы имеете в виду, как я буду использовать репозиторий Campaign и если его следует использовать из домена - нет, его не следует использовать изнутри домена. Если ты имеешь в виду, если я вставлю хранилище в хранилище - ты слишком много слушаешь xzibit .

0 голосов
/ 08 августа 2011

Вы сможете выполнить все вышеперечисленное с помощью следующего метода хранилища:

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...
}

Вот как я это делаю, и это работает очень хорошо.

...