Реализация шаблона хранилища и сервиса с помощью RavenDB - PullRequest
11 голосов
/ 23 марта 2011

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

Допустим, мне нужно выбрать все элементы, где парентида равна 1. Одним из способов является использованиеIQueryable List () и получить все документы, а затем добавить предложение where, чтобы выбрать элементы, в которых значение parentid равно 1. Это кажется плохой идеей, потому что я не могу использовать какие-либо функции индексирования в RavenDB.Таким образом, другой подход заключается в том, чтобы в репозитории было что-то вроде IEnumerable Find (строковый индекс, предикат Func), но это также кажется плохой идеей, потому что он недостаточно универсален и требует, чтобы я реализовал этот метод, если я изменюсь с RavenDBк обычному серверу sql.

Итак, как мне реализовать универсальный репозиторий, но при этом получить преимущества от индексов в RavenDB?

Ответы [ 4 ]

10 голосов
/ 24 февраля 2012

Это сообщение очень хорошо подводит итоги:

http://novuscraft.com/blog/ravendb-and-the-repository-pattern

10 голосов
/ 23 марта 2011

Прежде всего, спросите, почему вы хотите использовать шаблон хранилища?

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

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


ОДНАКО, давайте кратко рассмотрим одну часть вашего вопроса, прежде чем продолжить мой ответ:

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

Вы идете по этому пути неправильно - попытка сделать вашу систему полностью независимой от настойчивости на этом уровне порождает проблемы - если вы пытаетесь скрыть уникальные возможности вашего хранилища данных от самих запросов, тогда зачем использовать RavenDB?

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

Спросите себя, почему вы хотите запросить ваши документы по родительскому идентификатору? Это для отображения списка на странице? Почему вы пытаетесь смоделировать это с точки зрения документов тогда? Почему бы не смоделировать это с точки зрения модели представления и использовать наиболее эффективный метод получения этих данных из RavenDB? (Запрос по индексу (динамическому или иному)), прикрепите его к фабрике, которая берет «некоторые входные данные» и генерирует «выходные данные», и если вы решите изменить свое хранилище постоянных данных, вы можете изменить эти фабрики. (Я делаю еще один шаг в своих приложениях ASP.NET MVC, и у меня есть контроллеры с одним действием, и я не называю их контроллерами, делая запрос из них в большинстве случаев).

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

* * TL тысяча двадцать-один; DR * * тысяча двадцать-дв

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

8 голосов
/ 23 марта 2011

Допустим, мне нужно получить все предметы где парентида равна 1.

Во-первых, перестаньте думать о ваших потребностях в доступе к данным таким образом.

Вы НЕ должны " получить все предметы, где парентида равна 1 ". Это поможет попытаться перестать мыслить таким ориентированным на данные способом.

Что вам нужно, это выбрать все предметы с определенным родителем. Это концепция, которая существует в вашем проблемном пространстве (домен вашего приложения).

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

Одним из способов является использование IQueryable List () и получить все документы, а затем добавить предложение where для выбора элементов где парентида равна 1. Это кажется плохой идеей, потому что я не могу использовать любые функции индекса в RavenDB. Так Другой подход заключается в том, чтобы иметь как то так, IEnumerable Найти (строковый индекс, предикат Func) в хранилище, но это также кажется как плохая идея, потому что

Обе эти идеи плохие. Вы предлагаете, чтобы код, вызывающий ваше хранилище или запрос, обладал знаниями о вашей схеме.

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

Каждое место, где выбираются предметы с определенным родителем.

Это плохо, это антитеза инкапсуляции.

Мое мнение таково, что вы захотите моделировать запросы как явные понятия, а не как лямбда или строки, передаваемые и используемые повсеместно.

Вы можете явно моделировать запросы с помощью шаблона Спецификации, именованных методов запросов в хранилище, шаблона Объекта запроса и т. Д.

это не так достаточно общий и требует, чтобы я реализовать этот метод, если бы я перейти с RavenDB на общий sql сервер.

Хорошо, что Func слишком обобщенно. Опять же, подумайте, что нужно знать вашему потребляющему коду для того, чтобы использовать такой метод запросов, вы будете привязывать верхние уровни вашего кода непосредственно к вашей схеме БД, делая это.

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

5 голосов
/ 23 марта 2011

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

За последнее время Айенде опубликовал несколько сообщений на эту тему:

Я рекомендую просто писать против нативного API Raven.

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

...