Как реализовано разделение командных запросов (CQS) при использовании ORM?

StackOverflow https://stackoverflow.com/questions/1295686

  •  18-09-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

Я предполагаю, что под CQS вы имеете в виду архитектурный шаблон DDD, он же CQRS, не строго традиционный Ответы на вопросы принцип.

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

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

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

Другие советы

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

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

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

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

1) Возможность оптимизировать SQL-запросы и использовать расширенные функции хранилища БД, не абстрагированные в уровень ORM

2) Меньше накладных расходов

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

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

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

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

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

Nhibernate ( Гибернация ) для команд - красиво отображает мою доменную модель

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top