2010-04-13 3 views
2

Я читал на MVC 2 и рекомендуемых моделей, до сих пор я пришел к выводу (среди много волос потянув и полной растерянности), что:Архитектура с NHibernate и Хранилища

  • Модель - это просто базовый контейнер данных
  • Repository - обеспечивает доступ к данным
  • Service - обеспечивает бизнес-логику и действует как API к контроллеру

Контролер беседует с Службой, Служба ведет переговоры с Репозиторием и Моделью. Так, например, если бы я хотел, чтобы отобразить страницу сообщения в блоге с его комментариями, я мог бы сделать:

post = PostService.Get(id); 
comments = PostService.GetComments(post); 

Или, я сделал бы:

post = PostService.Get(id); 
comments = post.Comments; 

Если да, то где это существо набор, из хранилища? проблема в том, что он не ленивый загружен .. это не огромная проблема, но потом я сказал, что я хотел бы перечислить 10 сообщений с первым 2 комментариями для каждого, id должен загружать сообщения, а затем цикл и загружать комментарии, которые становятся беспорядочными.

Все примеры использования репозитория «InMemory» для тестирования и говорят, что в том числе материал db будет недоступен. Но это оставляет мне много пробелов, поэтому для начала кто-нибудь может прокомментировать сказанное выше?

+0

Просто для того, чтобы сделать это яснее, я понимаю, что NHibernate будет заполнять post.Comments для меня .. но если я затем обменяю репозиторий на другой поставщик данных, скажем, простой SQL, а затем отправьте сообщение. Комментарии не заселены для меня и не будут ленивы загружаться. Так использует post.Comments, нарушающий шаблон хранилища? Я чувствую, что NHibernate не должен зацикливаться на моделях, если, например, у всех моих моделей нет интерфейсов, и весь доступ к данным напрямую зависит от моделей, зависящих от поставщика данных, который затем полностью удаляет репозитории из решения .. * более запутанный * :( – Matthew

ответ

1
post = PostService.Get(id); 
comments = post.Comments; 

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

Вам нужно настроить отображение NH для проведения ленивой загрузки. (fetch = subselect batch-size = #), в противном случае интенсивная загрузка приведет к возврату слишком большого количества данных, а ленивая загрузка приведет к проблеме выбора N + 1 (1 запрос для извлечения сообщений, + N запросов для извлечения комментариев, где N количество сообщений - ваш цикл).

Если ваше требование действительно отображает 2 комментария для каждого сообщения, будет производиться серийный номер 2, но, как вы, без сомнения, догадались, как только ваше приложение попытается получить доступ к 3-му комментарию, NH выполнит другой выберите, чтобы заполнить коллекцию комментариев еще 2, так что вам может потребоваться более крупный размер партии с самого начала. Планируйте фазу настройки, когда вы знаете свои варианты использования. Это может быть очень сложно, если вы разрабатываете API доступа к данным общего назначения. (Кроме того, вам нужно добавить order-by = "SOME_COLUMN_NAME" в ваше сопоставление коллекции комментариев, чтобы контролировать, как получить «первые» комментарии). Легко недооценивать важность настроек NH-сопоставлений; ORM решает многие проблемы с разработчиками, но добавляет целый мир новых.

«Домен Driven Design» Эрика Эванса определяет шаблон хранилища &. Они не всегда подходят. Я прекратил использовать их для всех, кроме очень сложных проектов, и редко в сборках MVC. Преимуществами шаблона репозитория & являются разделение, изоляция, тестируемость и гибкость ваших архитектурных компонентов. В реальных условиях - рассмотрите свои пространства имен «usings». Если вы предпочитаете избегать использования «nhibernate» в своих контроллерах, тогда спрячьте его в репозитории и просто обратитесь к сборке репо.

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

Преимущества сервисного уровня включают полное скрытие механизма доступа к данным, демонстрацию методов обслуживания удаленно по сравнению с другими вариантами транспорта (например, веб-сервисы) и скрытие общих методов репозитория с дружественными API-адресами. Например, post = MyAwesomeAPI.PostService.Get (id); может просто быть оберткой для общего типа - получить любой тип по id - Repository.Get (id); Эта обертка API очень полезна при разработке набора сервисов для третьих сторон, потребляющих или просто других разработчиков в вашей команде. Если ваши сигнатуры методов остаются неизменными, вы можете изменить базовую реализацию в любое время - ваш переход с NH на простой SQL, например, не нарушит существующие приложения, которые потребляют этот API.

Для максимальной гибкости вы даже не свяжете свою сборку услуг с вашей сборкой репо. Скорее вы бы использовали инструмент инъекции зависимостей, такой как Structure Map, чтобы связать все с ним во время выполнения. Это позволяет переключать реализации репо только по конфигурации без перекомпиляции/связывания. Вы даже можете использовать несколько методов доступа к данным. Потребитель API не будет знать и не должен заботиться.

Если вам не нужны какие-либо из этих вещей, поставьте «использование nhibernate» в свои контроллеры и сделайте это. Риск состоит в том, что вы тесно связали свое приложение MVC с NH, и каждый должен знать все, чтобы сделать небольшое изменение в вашем приложении. Это решение, скорее всего, будет связано с вашими проектными ограничениями (время/деньги/люди/календарь). Если вам все это нужно, посмотрите архитектуру Sharp или соберите свой собственный стек. MVC намного больше VC, чем M.

Смежные вопросы