2015-12-19 4 views
2

У меня возникла проблема с несколькими агрегатами за одну транзакцию.Множественные агрегированные экземпляры в одной транзакции

У меня есть много узлов, структурированных в дереве. Узел может ссылаться на свой родительский узел по идентификатору. У узла много методов записи.

public class Node { 
    private NodeID nodeID; 

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

Мы можем построить tree structure из узлов. Но есть концепция working tree structure. К working tree structure, вы можете add operations, которые являются просто операциями, которые вы можете выполнять в узлах. Например ChangeParentOperation

public class WorkingTreeStructure { 
    private Array<Operation> operations; 

    public void add(Operation operation); 
} 

Там может быть только один working tree structure в то же время, и это может существует до тех пор, пока пользователь хочет, пока мы apply it. Applying it to the tree structure, в основном средство для каждой операции find node и call node's method, с необходимыми аргументами. Такие working tree structure могут модифицировать большое количество узлов. И мы должны это сделать: apply all operations или none (если есть ошибка).

Согласно принципам Вона Вернона, мы можем создать множество узлов в одной транзакции. Но нам нужно также модифицировать/удалить множество узлов в одной и той же транзакции.
Итак, что мне делать в такой ситуации?

+1

Здесь не хватает всего анализа домена и транзакций, который вы сделали (или не сделали). Как совместное использование вашего домена? Зачем выбирать «узел» как совокупный корень? Сколько одновременного доступа к «Узлу»? Какие инварианты он применяет? Случается ли, что «Узел» изменяется только один, а не как часть изменения структуры дерева? так далее и так далее. – guillaume31

+0

Я нашел способ сделать это. Я создал TreeStructure aggregate root, которые имеют прямую ссылку на узлы. Каждый узел может иметь прямую ссылку на дочерние узлы. По каждому запросу я не воссоздаю весь агрегат из db, потому что он может содержать до 3000 узлов, поэтому я сохраняю свежую TreeStructure в кеше. Благодаря этому у меня есть один агрегат, который можно свободно изменять и отвечать на вопрос о параллелизме здесь не проблема. :) – Dariss

ответ

0

Операция здесь является примером шаблона команды, если я правильно понимаю вещи. Так это выглядит примерно так

class Operation { 

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

Если вы осуществить вашу работу, как это, что также означает, что вы можете speicfy операцию отмены. Например, как этот

class DeleteNode : Operation { 

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

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

Теперь вы можете реализовать сделку как этот

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(); 
     } 
    } 
} 

Advanced чтения: В зависимости от языка/набор инструментов/рамки вы используете именно некоторые из них могут иметь поддержку за отмененные транзакции, и вы можете положиться на это.

Один я хотел лично PostSharp http://www.postsharp.net/blog/post/New-in-PostSharp-32-UndoRedo

Другой часто проще всего просто сохраняются данные и загрузить предыдущую версию, если вы хотите сделать откат назад

0

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

Вы на правильном пути. Для класса WorkingTreeStructure просто нужна функция «применить», которая применяет операции к узлам дерева и завершает структуру рабочего дерева.

public class WorkingTreeStructure { 
    private Array<Operation> operations; 

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

Это имеет смысл, учитывая ваш домен:

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