2015-12-19 1 views
2

Je rencontre un problème avec plusieurs agrégats dans une transaction.Plusieurs instances agrégées dans une transaction

J'ai beaucoup de nœuds structurés dans un arbre. Le noeud peut référencer son noeud parent par son ID. Le noeud a beaucoup de méthodes d'écriture.

public class Node { 
    private NodeID nodeID; 

    public void changeNodeData(NodeData nodeData); 
    public void changeParent(Node node); 
    public void changeType(Type type); 
    //... next write methods 
} 

Nous pouvons construire tree structure à partir de noeuds. Mais il y a le concept de working tree structure. Pour working tree structure, vous pouvez add operations, qui ne sont que des opérations que vous pouvez effectuer sur les nœuds. Par exemple ChangeParentOperation

public class WorkingTreeStructure { 
    private Array<Operation> operations; 

    public void add(Operation operation); 
} 

Il ne peut y avoir qu'un seul working tree structure en même temps et il peut existe aussi longtemps que l'utilisateur veut, jusqu'à ce que nous apply it. Applying it to the tree structure, signifie essentiellement pour chaque opération find node et call node's method, avec les arguments nécessaires. working tree structure peut modifier un grand nombre de nœuds. Et nous devons le faire: apply all operations ou none (s'il y a une erreur). Selon les principes de Vaughn Vernon, nous pouvons créer beaucoup de nœuds en une seule transaction. Mais nous avons besoin de modifier/supprimer beaucoup de nœuds dans la même transaction ici aussi.
Alors, que dois-je faire dans une telle situation?

+1

Il nous manque toute l'analyse de domaine et transaction que vous avez faite (ou n'avez pas fait) ici. Dans quelle mesure votre domaine est-il collaboratif? Pourquoi choisir 'Node' comme une racine agrégée? Combien y a-t-il d'accès simultané à un «nœud»? Quels invariants fait-il appliquer? Est-il arrivé qu'un 'Node' soit modifié seul, et non dans le cadre d'une modification de la structure arborescente? etc., etc. – guillaume31

+0

J'ai trouvé le moyen de le faire. J'ai créé la racine d'agrégat TreeStructure, qui contient une référence directe aux nœuds. Chaque nœud peut avoir une référence directe aux nœuds enfants. À chaque requête, je ne recréerai pas l'agrégat entier à partir de DB, car il peut contenir jusqu'à 3000 nœuds, donc je garde la nouvelle arborescence en cache. Merci à cela, j'ai un agrégat, qui peut être modifié librement et répondre à votre question de la concurrence n'est pas un problème ici. :) – Dariss

Répondre

0

Une opération ici est un exemple du modèle de commande si je comprends bien les choses. Il semble donc quelque chose comme ça

class Operation { 

    public void Execlute() { 
     /* modify node here */ 
    } 
} 

Si vous implémentez votre opération comme ce qui signifie que vous pouvez également speicfy une opération d'annulation. Par exemple, comme ce

class DeleteNode : Operation { 

    public override void Execute() { 
     /* delete node here */ 
    } 

    public override void Undo() { 
     /* reinsert node here */ 
    } 
} 

Maintenant, vous pouvez mettre en œuvre votre transaction comme celui-ci

public void ExecuteTransaction(Array<Operation> operations) { 

    bool exception = false; 
    int index = 0; 

    try { 
     for(; index < operations.length; ++index) { 
      operations[i].execute(); 
     } 
    } 
    catch (exception ex) { 
     exception = true; 
    } 

    if (exception) { 
     for(;index >= 0; --index) { 
      operations[index].undo(); 
     } 
    } 
} 

lecture avancée: En fonction de la langue/jeu d'outils/cadre que vous utilisez exactement certains d'entre eux pourraient avoir le soutien pour les transactions annulables et vous pouvez compter sur cela.

Un j'aime est personnellement PostSharp http://www.postsharp.net/blog/post/New-in-PostSharp-32-UndoRedo

Une autre façon souvent plus facile est de persister simplement vos données et charger une version précédente si vous voulez faire un rollback

0

L'agrégat devrait être l'arbre lui-même plutôt que les noeuds de ces arbres. Ainsi, lorsque vous modifiez une collection de nœuds dans un arbre, la transaction ne couvre qu'une racine agrégée (l'arbre) plutôt qu'une collection de racines agrégées (les nœuds individuels).

Vous êtes sur la bonne voie. La classe WorkingTreeStructure a simplement besoin d'une fonction "apply" qui applique les opérations aux nœuds de l'arbre et finalise la structure arborescente de travail.

public class WorkingTreeStructure { 
    private Array<Operation> operations; 

    public void add(Operation operation) {...} 
    public void apply() {...} 
} 

Cela est logique compte tenu de votre domaine:

Il ne peut y avoir qu'une seule structure arborescente travaillant en même temps et il peuvent exister aussi longtemps que l'utilisateur veut, jusqu'à ce que nous appliquons il