Comment Commande requête de séparation (CQS) mis en œuvre lors de l'utilisation d'un ORM?

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

  •  18-09-2019
  •  | 
  •  

Question

Le principe du modèle architectural CQS est que vous séparez vos requêtes et commandes en chemins distincts. Idéalement, votre magasin de persistance peut être lecture / écriture cloisonné, mais dans mon cas, il y a une seule base de données normalisée.

Si vous utilisez un ORM (NHibernate dans mon cas), il est clair que l'ORM est utilisé lors de l'émission des commandes. Mais qu'en est-toutes les différentes questions que vous devez exécuter pour former des données (DTO) pour les écrans des utilisateurs, est-il pratique courante de fossé le ORM lorsque vous faites du côté de la requête de CQS?

Où dois-je mettre en œuvre mes requêtes et projections DTO? ADO.NET droite (DataReaders, DTO, DataTables) stockés procs? Certaines requêtes sont tout à fait unique et impliquent beaucoup de jointures pour tirer tout ensemble. Je ne veux pas dénormaliser la base de données pour les requêtes, mais je pourrais créer des vues (la dénormalisation du pauvre).

Était-ce utile?

La solution

Je suppose par CQS-vous dire le modèle architectural DDD alias CQRS , pas strictement le CQS principe.

Je encore utiliser NHibernate pour votre lecture seule modèle. Il y a de nombreux avantages tels que les requêtes futures et multi, le chargement paresseux / désireux etc ... qui optimiseront DB chattiness. De plus, il sera plus facile de composer des requêtes avec un ORM si l'interface utilisateur permet à l'utilisateur de modifier essentiellement la clause where.

En ce qui concerne la façon de traiter techniquement un modèle en lecture seule, vous pouvez marquer une entité immuable avec NHibernate. Vous pouvez simplement marquer toutes vos entités de modèle de lecture immuable. De plus, je ne pense pas que vous pouvez mettre à jour des projections dans NHibernate de sorte que est une autre option pour aller comme lu seul modèle (Quelqu'un s'il vous plaît me corriger si je me trompe car je ne suis pas sûr à 100%).

En ce qui concerne les correspondances NH laids ou impossibles: NH peut mapper des vues et des procédures stockées, donc je pense qu'il serait bon d'utiliser ceux-ci lorsque vous avez besoin. Les vues sont probablement un peu plus flexible que les procédures stockées pour une lecture seule scénario parce que votre SQL sera toujours dynamique. Toutefois, si vous avez besoin de lecture / écriture pour l'une de ces structures aplaties je associez à une procédure de magasin.

Autres conseils

En fin de compte, l'idée est que vous devez utiliser tout ce qui fait le canal de requête plus facile pour vous de construire et de maintenir. Vous n'avez plus à vous soucier des mises à jour, l'application des règles d'affaires, le maintien de l'intégrité des données, ou même la charge de manutention (pour la plupart). Donc, vous êtes libre de choisir de nombreuses options qui étaient auparavant pas sur la table.

Mais NHibernate peut encore être une bonne option ... il est tout simplement plus la valeur par défaut automatique (ce qui est parfois le côté commande).

Nous avons choisi d'utiliser Castle Active Record (qui est basé sur NHibernate sous le capot), principalement parce qu'il a une fonctionnalité intéressante qui va générer une table pour vous d'une classe. Cela correspond très bien pour nous, car voici notre flux de travail: Tout d'abord, nous créons une classe ViewModel. Cette classe est en forme entièrement pour les besoins de la vue. Ensuite, nous marquons que ViewModel avec Castle attributs Active Record. Ensuite, nous demandons Active Record pour générer la table correspondante pour cette classe dans la base de données de requête. Ceci est le plus rapide, plus douce façon dont nous avons trouvé pour obtenir rapidement une table de base de données de requête qui sert la classe ViewModel. La génération automatique reflète la réalité que la seule raison pour laquelle existe la table est de servir la vue.

Nous utilisons EF pour la partie commande et ADO.NET droite => DTO pour la chaîne de requête. Avantages:

1) Capacité à optimiser les requêtes SQL et utiliser magasin avancé DB fonctionnalités non dans la couche abstraite ORM

2) Moins de tête

Mais nous utilisons la séparation que pour les pièces exigeantes (recherche), le reste repose sur le modèle commun Entity Framework.

Il n'y a pas besoin d'utiliser une approche différente de la lecture de votre base de données par rapport à la mise à jour de votre base de données. CQS indique simplement que les commandes qui mettent à jour la banque de données doit être séparé des requêtes qui lisent l'état de la banque de données.

Vous pouvez toujours utiliser NHibernate pour lire à partir de votre magasin de données, mais vous pouvez le rendre évident en créant deux classes différentes pour encapsuler votre accès aux données. Une classe aurait des méthodes pour lire (requête), la banque de données, l'autre classe aurait des méthodes pour envoyer des commandes (ajouter, mettre à jour, suppression) à la banque de données.

Ce que vous essayez d'éviter est une méthode qui reçoit un message de la base de données, et marque le message comme lu dans la base de données. Cela devrait être deux appels de méthodes distinctes. Vous ne devriez pas changer l'état et retourner une valeur de la même méthode.

Je tiens à garder séparé de ORM pour lit et écrit donc j'utiliser (et je l'utilise):

Nhibernate pour les commandes - cartes magnifiquement mon modèle de domaine

Dapper.net pour les requêtes - cartes magnifiquement mon DTO et permet felxibility si la requête est trop complexe

.

Ils sont un couple parfait comme Han Solo et Chewbacca.

scroll top