Je commence par DDD et je comprends que les racines agrégées sont utilisées pour assurer la cohérence transnationale. Nous ne devons pas modifier plusieurs agrégats dans un seul service d'application.
Je voudrais cependant savoir comment faire face à la situation suivante.
J'ai une racine agrégée appelée Produits.
Il existe également une racine agrégée appelée Group.
Les deux ont des identifiants et peuvent être modifiés indépendamment.
Plusieurs produits peuvent pointer vers le même groupe.
J'ai un service d'application qui peut changer le groupe d'un produit:
ProductService.ChangeProductGroup(string productId, string groupId)
- Vérifier que le groupe existe
- Obtenir le produit du référentiel
- Définir son groupe
- Réécrire le produit dans le référentiel
J'ai également un service d'application où le groupe peut être supprimé:
GroupService.DeleteGroup(string groupId)
1. Obtenez les produits du référentiel dont groupId est défini sur groupId fourni, assurez-vous que le nombre est 0 ou abandonnez 2. Supprimez le groupe du référentiel de groupes 3. Enregistrez les modifications
Ma question est le scénario suivant, que se passerait-il si:
Dans ProductService.ChangeProductGroup, nous vérifions que le groupe existe (il le fait), puis juste après cette vérification, un utilisateur distinct supprime le productGroup (via l'autre GroupService.DeleteGroup). Dans ce cas, nous avons défini une référence à un produit qui vient d'être supprimé?
Est-ce un défaut dans ma conception dans la mesure où je devrais utiliser une conception de domaine différente (en ajoutant des éléments supplémentaires si nécessaire), ou devrais-je utiliser des transactions?
Pourquoi ne stockez-vous pas les ID de produit dans l'entité Groupe? De cette façon, vous n'avez affaire qu'à un seul agrégat, ce qui facilitera les choses.
Vous devrez ensuite implémenter un type de modèle de concurrence, par exemple. Si vous choisissez une concurrence optimiste, ajoutez simplement une propriété de version à l'entité Group et lancez une exception si les versions ne correspondent pas lors de la mise à jour.
Ajouter un produit à un groupe
Beaucoup d'ORM ont une concurrence optimiste intégrée en utilisant des identifiants de version ou des horodatages, mais il est facile de faire le vôtre. Voici un bon article sur la façon dont cela se fait à Nhibernate http://ayende.com/blog/3946/nhibernate-mapping-concurrency .
la source
Bien que les transactions puissent aider, il existe un autre moyen, surtout si votre scénario se limite à quelques cas.
Vous pouvez inclure des vérifications dans les requêtes qui effectuent les mutations, ce qui fait de chaque paire de vérifications et mutations une opération atomique.
La requête interne de mise à jour du produit rejoint le groupe (nouvellement référencé). Cela le fait ne rien mettre à jour si ce groupe est parti.
La requête de suppression de groupe joint tous les produits pointant vers elle et a la condition supplémentaire que (n'importe quelle colonne de) le résultat de la jointure doit être nul. Cela lui permet de ne rien supprimer si des produits le désignent.
Les requêtes renvoient le nombre de lignes qui correspondent ou ont été mises à jour. Si le résultat est 0, vous avez perdu une condition de concurrence et n'avez rien fait. Il peut lever une exception et la couche application peut gérer cela comme bon lui semble, par exemple en réessayant depuis le début.
la source