1

我需要问一个复杂的场景,所以我将尝试举例说明。

考虑以下模型:

public enum States { Created, Approved, Started, Completed }

public class Request {
    States State {get; set;}
    IEnumerable<RequestLine> Lines {get; set;}
}

public class RequestLine {
    States State {get; set;}
    Request Request {get; set;}
    IEnumerable<WorkOrder> WorkOrders {get; set;}
}   

public class WorkOrder {
    States State {get; set;}
    RequestLine RequestLine {get; set;}
    IEnumerable<WorkOrderAction> Actions {get; set;}
}

public class WorkOrderAction {
    States State {get; set;}
    WorkOrder WorkOrder {get; set;}
}

所以每条记录都有一个状态,它们都是相互关联的。创建 WorkOrderAction 时,我必须更新 WorkOrder 状态,然后是 RequesTLine 状态,然后是 Request 状态。对于每个 WorkOrderAction 记录,我应该检查其他子记录状态并更新父记录。

我可以使用我不喜欢的数据库触发器来做到这一点。我在应用程序级别使用 Devexpress XAF,因此我也可以在那里编写一些逻辑。但我仍然无法决定哪种方法更好。

链接状态机有一个共同的概念吗?

4

3 回答 3

2

我们只需要知道“其他不完整的孩子”。

  1. 我们可以枚举所有它们:foreach(parent.Children) if(child.State != Completed)。但是这将加载它们,因此会对性能产生影响
  2. 我们可以使用类似 Execute(new BinaryOperator("State", Completed, NotEquals), AggregateOperand.Count) 之类的方法执行到数据库的往返。这需要对域进行重组,并且对性能的影响小于前一个。
  3. 当每个孩子被保存/删除/删除/添加时,我们可以更新父母的“IncompletedChildren”成员(整数)。始终加载 Parent 对象,因此我们可以在“IncompletedChildren == 0”时确定父对象已完成,将其标记为已完成并递归强制完成其父对象。没有额外的流量负载(一个“整数”不是“加载”恕我直言)。然而,这种方法会为每个“IncompletedChildren”更新强制“OptimisticLoading”增量——这使得这种方法在某些情况下无法使用。

我会推荐第二种方法。

PS:在我们的项目/任务系统中,我们引入了带有表达式“Items [State <> Completed].Count 的计算字段。但是这在现实中行不通。大多数时候至少在我们的系统中,Completed 状态并不意味着一切都完成了:)

于 2011-09-21T11:19:23.853 回答
0

通常的做法与状态机没有任何关系。也就是说,在执行数据完整性规则方面,状态机并不特殊。

如果它必须适用于所有用户,那么在触发器中实现它是有意义的。只有由 dbms 控制的代码才能对所有用户强制执行数据完整性规则。(所有用户都包括睡眠不足的 DBA 和她的命令行工具。)

于 2011-09-20T17:38:15.653 回答
0

不完全确定我理解这个问题,但如果您询问强制执行数据完整性“级联”(级联更新),那么我会考虑设置“可延迟”约束,这将推迟检查约束检查直到发出提交. 然后,您将根据需要对父/子进行更新,然后提交。

这是有关Oracle的可延迟约束的链接。

于 2011-09-20T17:47:08.283 回答