#asp.net-mvc-3 #architecture #ravendb
#asp.net-mvc-3 #архитектура #ravendb
Вопрос:
Я очень новичок в RavenDB и MVC3, в частности, в использовании (не концепции) IoC. Итак, просто чтобы предупредить вас, что это будет звучать как вопрос для очень начинающих.
В заключение: у меня есть модель предметной области, допустим, это
public class Goose
Внутри этого класса у меня может быть более сложный объект в качестве свойства
public Beak beak { get; set; }
В RavenDB нам справедливо рекомендуется [JsonIgnore] это свойство или не иметь его вообще и вместо этого иметь ссылочный идентификатор, например
public String beakId { get; set; }
Где-нибудь по пути в моем приложении MVC3 я захочу просмотреть гуся, и, возможно, я захочу отобразить пользователю что-нибудь о Гусе и его клюве (должно ли это быть клювом?). Итак, да, мне нужна модель представления, верно?
public class GooseModel
{
public String BeakColour { get; set; }
public String BeakLength { get; set; }
...etc
}
Верно, итак, предполагая, что у меня есть какое-то хранилище GooseRepository и какое-то хранилище BeakRepository, вот простой вопрос….
Я нахожусь в классе GooseController и загружаю Goose для просмотра. В какой момент я использую BeakRepository и кто должен знать об этом? GooseController знает о GooseRepository и загружает Goose по идентификатору. На данный момент у нас могло бы быть какое-то свойство внутри класса Goose, которое представляет весь Beak, но я действительно не хочу вводить BeakRepository в GooseRepository, не так ли? Хорошо, возможно, когда я создам GooseModel из найденного мной Goose, я смогу получить свойства GooseModel для BeakColour и BeakLength, каким образом? Ну, мне нравится AutoMapper, поэтому, возможно, моя карта для GooseModel из Goose использует BeakRepository для поиска Beak, а затем извлекает два свойства Beak для заполнения полей GooseModel.. это тоже кажется неправильным… итак, что осталось? GooseController.. должен ли контроллер Goose знать о BeakRespository, а затем находить и устанавливать BeakColour и BeakLength!? это, безусловно, тоже кажется совершенно неправильным..
Итак, где это делается? контроллер, доменный объект, mapper или что-то еще? Возможно, у меня должно быть частичное представление типа Beak, который используется в представлении Goose?..
Комментарии:
1. Я бы на самом деле сказал, что в Raven вы, вероятно, хотите, чтобы Beak был сложным объектом / свойством goose, а не отдельным документом. Как правило, примеры для такого рода вещей очень, очень плохие, когда дело доходит до documentdbs.
Ответ №1:
Я склонен объединять такого рода логику в сервис / бизнес-уровень ( GooseService
), который я затем внедряю в контроллер. ваш уровень обслуживания может принимать GooseRepository
и BeakRepository
и возвращать разрешенный объект, который сопоставил GooseViewModel
вместе.
Комментарии:
1. Ах, значит, GooseService будет нести ответственность за генерацию / отображение GooseModel? Я предполагаю, что здесь будет задействован какой-то распознаватель, который отвечает за предоставление GooseService?
2. правильно. в зависимости от ваших предпочтений, вы просто выбираете контейнер ioc и подключаете его. вам нужно будет создать пользовательский DependencyResolver для выбранного вами контейнера ioc, поскольку именно так будут построены ваши контроллеры. По умолчанию я использую structuremap, но ninject хорош, и я слышал хорошие отзывы о более новых версиях unity.
3. Спасибо! Я изучал их и начал со StructureMap, но я должен сказать, что я изо всех сил пытаюсь найти простой пример IoC с MVC3, который использует StructureMap и четко определяет, куда что поместить. Я могу видеть, как код будет выполняться и запускать UT, но неясно, как подключить его при запуске приложения asax
4. вот начало для завершения structuremap mvc3. это достойная реализация. stevesmithblog.com/blog / …
Ответ №2:
Хм, … читая ваш вопрос, я настоятельно рекомендую вам забыть о сервисном уровне и уровне хранилища. Если у вас нет действительно веских причин для их сохранения (тестирование не является одной из них, поскольку в RavenDB есть EmbeddableDocumentStore, что быстро и просто), извлеките их, чтобы воспользоваться некоторыми очень приятными функциями RavenDB.
На самом деле я написал пост о том, почему, по моему мнению, вам обычно следует избегать этих слоев:http://daniellang.net/keep-your-code-simple/ Речь идет о NHibernate, но концепции применимы и здесь.
Следует ли вам денормализовать свойства BeakColor и BeakLength в вашем документе Goose, зависит от потребностей ваших приложений. Если вас устраивает термин «совокупный корень», то эмпирическое правило заключается в том, что это, как правило, ваши документы. Если вы не уверены, следует ли применять денормализацию, избегайте ее и используйте .Include(goose => goose.Beak)
вместо этого при загрузке вашего Goose.
Пожалуйста, дайте мне знать, имеет ли это смысл для вас.
Комментарии:
1. В программировании никогда не бывает истинно «правильного» способа выполнения чего-либо, и я довольно разочарован количеством различных подходов к MVC3. Говоря это, ваше предложение отказаться от уровня репозитория интересно. В настоящее время я пытаюсь изучить наилучшую практику, поэтому «необходимость» на самом деле не является фактором. Я полагаю, я все еще мог бы использовать репозиторий и попросить его включить Beak при извлечении из Raven, а затем заполнить несериализованное свойство объекта из beakId. Я на правильном пути?
2. Ha! Я прочитал вашу статью, очень, очень хороший момент. Моя карьера началась с классического ASP-встроенного SQL с использованием ADO days, и я должен сказать, что я мог бы сделать все очень быстро. Конечно, я вырос из этого и использовал много материалов VB / C COM и позже .Net. Но у меня возникает неприятное чувство каждый раз, когда я начинаю с чего-то недавнего. Есть несколько замечательных идей, но их не обязательно использовать все сразу..
3. Рад слышать, что вам нравится идея. Что касается заполнения объекта Goose, я не уверен, что понимаю ваш вопрос. Это может помочь вам взглянуть на образец RaccoonBlog ( github.com/ayende/RaccoonBlog ). Если нет, вы также можете отправить мне электронное письмо.