Где разместить объектно-ориентированные запросы в многоуровневой архитектуре? - PullRequest
2 голосов
/ 23 сентября 2010

Дано:

  • У вас есть архитектура с представлениями слоев, бизнесом и данными.
  • Вы применяете доменный дизайн.
  • Вы используете объектно-реляционный маппер, который позволяет создавать объектно-ориентированные запросы (например, NHibernate, который позволяет создавать HQL-запросы).

Вопрос:

В какой слой следует помещать объектно-ориентированные запросы?

Мои мысли:

Я думаю, что помещать их на уровень представления обычно не имеет смысла. Но я не знаю, поместить ли их в бизнес или на уровень данных.

Пример (NHibernate):

Допустим, вашей бизнес-логике нужен какой-то метод GetCustomersPossblyInterestedIn (продукт p). Затем вы можете создать сложный HQL-запрос, который выбирает объекты клиентов, в которых клиент уже купил продукт той же категории, что и p.

Аргумент а)

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

Аргумент б)

С другой стороны, бизнес-уровень не должен зависеть от уровня данных, поэтому непосредственное использование NHibernate на бизнес-уровне вызывает тревожный звонок.

Возможное решение 1)

Создайте свой собственный объектно-ориентированный язык запросов, который вы используете на бизнес-уровне, и переведите на HQL на уровне данных. Я думаю, что это вызвало бы много накладных расходов. Если вы используете язык запросов, основанный на объектах запросов, а не на синтаксически проанализированном языке запросов, вы, вероятно, могли бы предпринять некоторые усилия, но мое возражение по-прежнему применимо.

Возможное решение 2)

Непосредственное использование NHibernate на бизнес-уровне - это нормально, потому что уровень абстракции, который NHibernate может предоставить с помощью HQL, ISession и т. Д., Соответствует бизнес-уровню. Нет необходимости его оборачивать.

Что вы думаете?

редактирует:

См. «Репозиторий - это новый Singleton» и «Ложный миф о инкапсуляции доступа к данным в DAL» Айенде Рахиен для тесно связанных обсуждений.

Ответы [ 3 ]

1 голос
/ 23 сентября 2010

Определенно, избегайте помещения объектно-ориентированных запросов на уровень представления.Он должен ТОЛЬКО отображать / использовать данные, полученные из уровня бизнес-логики (BLL).Без каких-либо запросов.Если вам нужно запросить результаты, полученные от вашего BLL, то ваш BLL должен быть расширен для предоставления таких данных, которые не нужно запрашивать.

Ваша идея использовать швы «объектно-ориентированного языка запросов», какхорошо.Обычно этот «язык» является вашим DAL :) Я бы сказал, что хорошим примером «объектно-ориентированного языка запросов» является правильно реализованный уровень доступа к данным (DAL).

С моей точки зрения, вы DAL должен реализовывать 80-90% всей функциональности и предоставлять такой набор функций:

  • Customer GetCustomerById (int customerId);
  • Список GetLastRegisteredCustomers (int count);
  • и т. Д. *

Эти функции обеспечивают большую часть требуемых функций, которые не нужно запрашивать.

Для всех остальных 10-20% редко используемыхзапросы (вы назвали их «объектно-ориентированными»), ваш DAL должен реализовать метод / методы, которые возвращают результат IQueryable, я бы сказал, по крайней мере, метод «GetAll ()» и, возможно, несколько настроек:

  • IQueryable GetAll ();
  • IQueryable GetCustomerByCountry (int countryId);

в этом случае, если вам потребуется найти клиента в стране, зарегистрированной в этом году, на ваш BLL, вы будете cвсе:

List<Customer> customers = GetCustomerRepository()
    .GetCustomerByCountry(countryId)
    .Where(customer=>customer.RegisterDate.Year==year)
    .ToList<Customer>()
    ;

Угадайте, вы знаете, что обеспечивает интерфейс IQueryable <>.

Как работать с Linq под NHibernate: Linq to NHibernate .

Еще один совет: я бы рекомендовал использовать шаблон «Репозиторий» для вашей реализации DAL.Некоторое время назад я использовал это для общей идеи: http://habrahabr.ru/blogs/net/52173/ (если вы не можете читать по-русски, переведите всю страницу с помощью Google - это должно быть читабельно).

Надеюсь, это поможет.

0 голосов
/ 23 сентября 2010

Запросы принадлежат хранилищу. Вы можете иметь сигнатуру функции для GetCustomersPossblyInterestedIn (Product p) везде, где это необходимо, но сам запрос должен быть только в классе репозитория

0 голосов
/ 23 сентября 2010

Я предпочитаю оборачивать NHibernate (или другой ORM), используя какой-нибудь репозиторий.Например,в случае NHibernate репозиторий обернет сеанс NHibernate.Это хранилище может быть для каждого класса (например, CustomerRepository и OrderRepository) или, если у вас не слишком много классов в вашем домене, вы также можете начать с одного хранилища.

Это идеальное место для размещения запросов Criteria (LoadAllByName, LoadCustomerWithOrder и т. Д.).Если вам позже потребуется переключиться на другой ORM или даже другой механизм сохранения (очень редко, я бы подумал), вы можете поменять весь слой данных, включая репозиторий.

...