2009-08-18 4 views
17

Принцип архитектурного шаблона CQS заключается в том, что вы отделяете свои запросы и команды от разных путей. В идеале, ваш хранилище персистентности можно разделить на разделы «чтение/запись», но в моем случае есть единственная нормализованная база данных.Как выполняется разделение запросов команд (CQS) при использовании ORM?

Если вы используете ORM (NHibernate в моем случае), ясно, что ORM используется при выдаче команд. Но как насчет всех различных запросов, которые нужно выполнить для формирования данных (DTO) для пользовательских экранов, является ли обычной практикой прерывать ORM при выполнении Query-стороны CQS?

Где я должен выполнять свои запросы и проекции DTO? Прямой ADO.NET (datareaders, dtos, datatables, хранимые процедуры)? Некоторые запросы совершенно уникальны и связаны с множеством попыток собрать все вместе. Я не хочу денормализовать базу данных для запросов, но я мог бы создавать представления (денормализация бедных).

ответ

8

Я предполагаю, что CQS означает архитектурный образец DDD aka CQRS, а не строго традиционный принцип CQS.

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

Относительно того, как технически обрабатывать модель только для чтения, вы можете отметить объект immutable с помощью NHibernate. Вы могли бы просто пометить все ваши прочитанные объекты модели неизменяемыми. Кроме того, я не думаю, что вы можете обновлять прогнозы в NHibernate, так что это еще один вариант для вашей модели только для чтения (кто-то, пожалуйста, поправьте меня, если я ошибаюсь, поскольку я не уверен на 100%).

Что касается уродливых или невозможных NH-сопоставлений: NH может отображать представления и хранимые процедуры, поэтому я думаю, что было бы хорошо использовать их, когда вам нужно. Представления, вероятно, немного более гибкие, чем хранимые процедуры для сценария только для чтения, потому что ваш SQL будет по-прежнему динамическим. Однако, если вам нужно читать/писать для любой из этих сплющенных структур, я бы привязал к процедуре магазина.

+0

Да, я имею в виду CQRS. Я думаю, что архитектурный подход имеет большой смысл, и я бы хотел использовать ORM по причинам, которые вы даете. Но как бы вы затронули вопросы, которые я затронул в отношении сложных сопоставлений DTO? Например, мне нужно сгладить иерархические и многие-ко-многим отношения, которые зависят от типов в дереве наследования. Я знаю, что это расплывчато, но просто предположим, что NHibernate (или любое ORM) сопоставление является неприятным в этих случаях. Не могли бы вы отобразить хранимую процедуру или точку зрения в этот момент или что? – pfries

+0

Простите меня, если вы уже знаете об этом: NH может отображать из представлений и procs. Таким образом, вы можете использовать представление или proc в БД, но все еще есть поиск/запрос через NH. –

+0

Да, это то, где я склоняюсь - сопоставление с представлениями и/или процессами. Я полагаю, что можно рассматривать представления/procs как модель db только для чтения. Это то, что я считаю денормализацией бедных. В CQRS вы можете использовать эти представления в таблицах в read-slaves, но в настоящее время они просто реализуются как представления. Может быть, это лучший способ подумать об этом. – pfries

1

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

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

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

+0

Я понимаю, что вы имеете в виду в отношении двух отдельных классов, чтобы сделать разделение явным, и я согласен. Но если я только запрашиваю, чтобы создать DTO, я действительно хочу использовать ORM для этого? Мне не требуется отслеживание изменений или единица работы. Мне нравится проекции/сопоставление, но мои DTO на стороне запроса не имеют ничего общего с моим графиком объектов объекта, а запросы иногда сложны - проще писать в представлении или хранимой процедуре, чем в HQL или с использованием критериев. Как создавать представления для DTO запросов? Хорошо для некоторых, но все? и я не уверен, что хочу сопоставить n-таблицы в NHib только для того, чтобы захватить DTO. СПАСИБО. – pfries

+1

Я вижу вашу точку зрения, я, конечно, изо всех сил пытался заставить HQL делать то, что я хочу, присоединяясь к нескольким таблицам. Я думаю, если у вас есть интерфейс, который определяет методы, которые вы используете для запроса, в конце концов реализация не имеет значения. Код в интерфейс и использовать то, что имеет смысл. Возможно, это сочетание Nhibernate и ADO.NET, или всех ADO.NET. Если позже вы обнаружите слабость по своему выбору, выполните новый конкретный класс, используя технологию, которая имеет смысл. Это сценарий, в котором вы наверняка знаете, что правильно, и похоже, что ORM ничего не добавляет в вашем сценарии. – NerdFury

3

Мы используем EF для командной части и прямые ADO.NET => DTO для цепочки запросов. Преимущества:

1) Возможность оптимизации запросов SQL и использовать передовые DB характеристики магазина не абстрагируется в ОРМ слой

2) Меньше накладных

Но мы используем разделение только для сложных деталей (поиск) , остальные полагаются на общую модель Entity Framework.

6

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

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

Мы решили использовать Замок Active Record (который основан на NHibernate под капотом), главным образом потому, что он имеет приятную функцию, которая будет генерировать таблицу для вас из класса. Это отлично подходит для нас, потому что здесь наш рабочий процесс: во-первых, мы создаем класс ViewModel. Этот класс полностью сформирован для нужд View. Затем мы отмечаем, что ViewModel с атрибутами Active Record Castle. Затем мы запрашиваем Active Record для создания соответствующей таблицы для этого класса в базе данных Query. Это самый быстрый, самый быстрый способ, с помощью которого мы быстро получили таблицу базы данных запросов, которая служит классу ViewModel. Автоматическое генерирование отражает реальность, что единственная причина, по которой существует таблица, - служить представлению.

+0

Как вы обрабатываете вставки/обновления для прочитанных таблиц? Вы используете обмен сообщениями? – pfries

+0

Да, мы используем nServiceBus, а объекты домена публикуют события при записи. Затем Абонент этих событий заполняет базу данных запросов. –

+0

Жемчужина дня. Раньше не нравился активный шаблон записи, но с cqrs это действительно имеет смысл. Благодарю. –

1

мне нравится держать ORM отделит для чтения и записи, так что я хотел бы использовать (и я использую):

Nhibernate для команд - прекрасно отображает мою модель домена

Dapper.net для запросов - красиво отображает мои DTO и допускает скользкость, если запрос слишком сложный.

Они идеальная пара, как Хан Соло и Чубакка.