Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 一个事务中有多个聚合实例_Java_C#_Transactions_Domain Driven Design_Cqrs - Fatal编程技术网

Java 一个事务中有多个聚合实例

Java 一个事务中有多个聚合实例,java,c#,transactions,domain-driven-design,cqrs,Java,C#,Transactions,Domain Driven Design,Cqrs,我在一个事务中遇到多个聚合问题 我有一个树结构的许多节点。 节点可以通过id引用其父节点。节点有许多写入方法 public class Node { private NodeID nodeID; public void changeNodeData(NodeData nodeData); public void changeParent(Node node); public void changeType(Type type); //... next w

我在一个事务中遇到多个聚合问题

我有一个树结构的许多节点。 节点可以通过id引用其父节点。节点有许多写入方法

public class Node {
    private NodeID nodeID;

    public void changeNodeData(NodeData nodeData);
    public void changeParent(Node node);
    public void changeType(Type type);
    //... next write methods
}
我们可以从节点构建
树结构。
但是有一种工作树结构的概念
。 要
工作树结构
,您可以
添加操作
,这些操作只是可以在节点上执行的操作。例如
ChangeParentOperation

public class WorkingTreeStructure {
    private Array<Operation> operations;

    public void add(Operation operation);
}
公共类工作树结构{
专用阵列操作;
公共作废添加(操作);
}
同一时间只能有一个
工作树结构
,它可以根据用户的需要存在多长时间,直到我们
应用它
将其应用于树结构
,基本上意味着对于每个操作
查找节点
调用节点的方法
,以及必要的参数。 这样的
工作树结构
可以修改很多节点。我们需要这样做:
应用所有操作
(如果有错误)

根据沃恩·弗农的原理,我们可以在一个事务中创建许多节点。但是我们也需要在这里修改/删除同一事务中的许多节点。

那么在这种情况下我应该怎么做呢?

如果我理解正确,这里的操作就是命令模式的一个例子。看起来是这样的

class Operation {

   public void Execlute() {
       /* modify node here */
   }
}
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();
        }
     }
 }
如果您实现这样的操作,这也意味着您可以指定撤消操作。比如像这样

class Operation {

   public void Execlute() {
       /* modify node here */
   }
}
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();
        }
     }
 }
现在您可以这样实现您的事务

class Operation {

   public void Execlute() {
       /* modify node here */
   }
}
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();
        }
     }
 }
public void ExecuteTransaction(数组操作){
布尔异常=假;
int指数=0;
试一试{
对于(;索引=0;--索引){
操作[index].undo();
}
}
}
高级阅读: 根据您正使用的语言/工具集/框架,其中一些可能支持可撤销的事务,您可能依赖于此

我个人喜欢的是postsharp


另一种通常更简单的方法是,如果要执行回滚,只需保存数据并加载以前的版本。聚合应该是树本身,而不是那些树的节点。因此,当您更改树中的节点集合时,事务只覆盖一个聚合根(树),而不覆盖聚合根集合(单个节点)

你在正确的轨道上。WorkingTreeStructure类只需要一个“apply”函数,该函数将操作应用于树的节点并最终确定工作树结构

public class WorkingTreeStructure {
    private Array<Operation> operations;

    public void add(Operation operation) {...}
    public void apply() {...}
}
公共类工作树结构{
专用阵列操作;
公共无效添加(操作){…}
public void apply(){…}
}
考虑到您的域,这是有意义的:

同时只能有一个工作树结构,并且 只要用户愿意,就可以存在,直到我们应用它


我们缺少了您在此处所做(或未做)的整个域和事务分析。你的领域有多协作?为什么选择
节点
作为聚合根?对
节点的并发访问量是多少?它执行什么不变量?是否曾经发生过这样的情况:
节点
是单独修改的,而不是作为树结构修改的一部分?诸如此类,我找到了办法。我创建了树状结构聚合根,它直接引用节点。每个节点都可以直接引用子节点。在每次请求时,我都不会从数据库中重新创建整个聚合,因为它最多可以容纳3000个节点,所以我会将新的树结构保存在缓存中。多亏了这一点,我有一个聚合,可以自由修改,在这里回答您的问题并发性不是问题。:)