База репозитория или конкретный метод? - PullRequest
4 голосов
/ 15 июля 2011

Я занимаюсь разработкой приложения и пытаюсь применить DDD и другие инструменты (Nhibernate и asp.net MVC).

В этом приложении у нас есть требование для реализации «поиска» с помощьюИмя в персоне лица хранилища.Итак, у нас есть база репозитория (класс RepositoryBase), и в этой реализации у меня есть универсальный метод, который работает для этого элемента.

public IEnumerable<T> FindAll(Expression<Func<T, bool>> condition) {
  return Session.QueryOver<T>().Where(condition);
}

И в моем приложении asv.net mvc мы могли бы использовать его следующим образом:

var list = _repositoryPerson.FindAll(x => x.Name == "Felipe");

С другой стороны, мы могли бы создать специальный метод (в классе RepositroyPerson) для этой задачи, например:

public IEnumerable<Person> FindByName(string name) {
  return Session.QueryOver<Person>().Where(x => x.Name == name);
}

в моем приложении asp.net mvc, мы могли быиспользуйте это как:

var list = _repositoryPerson.FindByName("Felipe");

Мои вопросы:

1 - Каков рекомендуемый способ выполнения этого требования в соответствии с DDD?Конкретный или базовый класс?

2 - Кто-то порекомендовал какую-нибудь хорошую реализацию базы репозитория (универсальной) с Nhibernate QueryOver?

, если кто-то может мне помочь, я был бы очень признателен!Спасибо


ОБНОВЛЕНИЯ:

Если мне нужно, например, сложный поиск, например, объединить условия ... например: имя (необязательно) и возраст (необязательно) и город (необязательно)) и другие поля .... каждое поле будет необязательным и объединяется с другими полями!Использование выражения будет рекомендовано или нет?Как бы вы реализовали этот код?

PS: Извините за мой английский!

Спасибо

Ответы [ 4 ]

4 голосов
/ 15 июля 2011

Чтобы получить лучшее из обоих миров, вы можете реализовать метод FindByName в общем, как в базовом классе, пометить его как protected или protected internal (в зависимости от того, хотите ли вы разрешить другие сборкидля определения реализаций репозитория), а затем вызовите его из ваших конкретных объектов репозитория.

protected internal IEnumerable<T> FindAll(Expression<Func<T, bool>> condition) {
  return Session.QueryOver<T>().Where(condition);
}

public IEnumerable<Person> FindByName(string name) {
  return base.FindAll(x => x.Name == name);
}

Это позволит вам написать конкретные тесты для случаев, когда вы будете использовать метод, а также позволит вам изменить свойРеализация ORM без необходимости изменять ее в куче мест.

ОБНОВЛЕНИЕ: Чтобы объединить несколько условий в FindAll, вы можете просто объединить их, используя Aggregate (я не проверял это с NHibernate, но еслиперерывы, вы можете заменить его на foreach).

public IEnumerable<T> FindAll(IEnumerable<Expression<Func<T, bool>>> conditions)
{
    return conditions.Aggregate(Session.QueryOver<T>(), (current, condition) => current.Where(condition)).List();
}

Тогда методы могут принимать необязательные параметры и создавать список условий, которые передаются в FindAll.

   public IEnumerable<T> FindByParams(string name=null, string city=null)
   {
       var wheres = new List<Expression<Func<T, bool>>>();

       if (name != null)
       {
           wheres.Add(x => x.Name == name);
       }
       if (city != null)
       {
           wheres.Add(x => x.City == city);
       }
       return base.FindAll(wheres);
   }
1 голос
/ 16 июля 2011

Дополнительные замечания:

Кто является потребителями вашего кода репозитория?Если вы предоставляете свой репозиторий графическому интерфейсу или другим разработчикам, которые могут бороться или злоупотреблять более абстрактным интерфейсом, то есть дополнительный стимул для обеспечения более четкого конкретного интерфейса.

Насколько раздут интерфейс?То, что выражение может быть почти чем-либо, не означает, что оно обычно есть.Но в тех случаях, когда это возможно, возможно, из-за того, что вы можете объединить критерии поиска, как в вашем обновлении, тогда это склоняется к использованию более абстрактных методов, по крайней мере, в качестве помощников.

Ура,
Беррил

1 голос
/ 15 июля 2011

Я согласен с Оскаром - я предпочитаю конкретные методы по той причине, что они гораздо более проверяемы. Очень сложно создать разумные тесты для объектов IQueryable и Expression.

1 голос
/ 15 июля 2011

оба метода работают, я буду использовать универсальный метод, но findmyname дает вам лучший и чистый код. я думаю, это вопрос вкусов и того, насколько пуристом в DDD вы хотите быть. я создам конкретные методы для более сложных требований, таких как поиск или что-то в этом роде, но для меня это просто:

...