All*_*nde 6 sql-server-2008 database-design relational-theory
我正在尝试对工作流(状态和活动)进行建模以创建“规则”。
让我给你举个例子。
主要的“对象”让我们说是“车辆要求”,我会有这张表:
idRequirement, idVehicle,DateOfRequirement, idStatus, LastUpdate
1 2 2012-01-02 10:20:00, 1 ,2012-01-02 10:20:00
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,因为寄存器刚刚创建,DateOfRequirement 和 LastUpdate 是相同的,LastUpdate 将在每次状态更改后更新。
状态表
idStatus,Status
1 New
2 Vehicle Assigned
3 Closed
Run Code Online (Sandbox Code Playgroud)
活动表
idActivitie, Activitie
1 Create Vehicle Requirement
2 Assign Vehicle
3 Close requirement.
4 ReAssign Vehicle.
5 Confirm
Run Code Online (Sandbox Code Playgroud)
直到上表我都没有问题,但我的问题是,例如:
我知道如果当前状态不是“车辆已分配”(idStatus=2),我无法关闭要求(在“车辆要求”上更新到 idStatus=3)。
我可以通过代码来做到这一点(或者我认为是这样),但是无论如何都可以将这种规则建模到表格中吗?我的意思是一个表格,我在其中检索下一个 idStatus 和要执行的活动(以保存每个需求及其活动的“kardex/历史”),例如检查活动或当前状态?
规则还将根据时间和状态设置 3 个“警报”。例如,分配车辆的“绿色”限制时间为 30 分钟或更短,黄色“警报”在创建需求后将在 31 到 45 之间(状态为新),红色警报将在 45 分钟后显示状态为“新”
idRequirement,Vehicle,CurrentStatus,NextStatus, Alert
1 N/A New Vehicle Assigned Green
Run Code Online (Sandbox Code Playgroud)
39 分钟后,它会是这样的:
idRequirement,Vehicle,CurrentStatus,NextStatus, Alert
1 N/A New Vehicle Assigned Yellow
Run Code Online (Sandbox Code Playgroud)
45 分钟后:
idRequirement,Vehicle,CurrentStatus,NextStatus, Alert
1 N/A New Vehicle Assigned Red
Run Code Online (Sandbox Code Playgroud)
如果还不够清楚,请告诉我尽量解释得更好。
与此同时,我只需要一个“工作流程”,我的意思是,在 idStatus=2 和 idStatus=3 之后,它的顺序始终是 idStatus=1,但是如果您想帮助我考虑诸如转到 idStatus=3 的情况在 idStatus=1 之后,我将非常感激。
我有一些想法(可能是坏的):
表规则:
idRule 名称 idCurrentState idNextState idActivitieToPerform GreenLimit YelloLimit 1 分配 1 2 1 30 45 2 CloseFromNew 1 3 3 30 90 3 换车 2 2 4 45 90 4 关闭要求 2 3 3 90 120 5 确认车辆 2 2 5 30 90
但是我遇到了很多麻烦,因为“idCurrentState”和“idNextState”指的是状态表上的相同主键。我的问候和感谢您的时间。
更新:
添加一些规则,让示例更清晰:
添加活动“重新分配车辆”
要考虑:
我 99% 确定只有 3 种“颜色”(因此我们不能忽略与颜色和任何其他表作为状态/活动的关系)。
不同的活动源自相同的状态(ChangeVehicle 和 Confirm)(多个活动)
不同状态的不同活动源自相同状态(非线性工作流)
非线性工作流程
好吧,根据Kevin Feasel的评论,我只是扩展了我的示例/问题(在“更新”文本之后解释了我需要完成的约束)
再次问好!
考虑到一些限制,您所拥有的可以工作:
根据您提到的要求,该解决方案符合大多数限制条件,但不符合 #2。不过,我会考虑几件事。
我要质疑的一件事是您是否完全需要该活动表。如果它真的是状态和活动之间的 1:1 对应关系,您可以将其打包成一张表而不会丢失:您的活动只是将您推到下一个状态的操作。但是,如果每个状态有多个活动,这可能是有意义的。如果您有一个总体状态类别(例如,当该行处于“车辆已分配”状态时,需要进行 5 个单独的活动才能使其处于“已关闭”状态),那么这个总体思路是可以的。
因此,如果每个状态有一个活动,则状态表将具有以下属性:
RedMax 是隐含的:只要当前时间与您要使用的任何时间(DateOfRequirement、LastUpdate 等)之间的差异大于 YellowLimit,它就是红色。
或者,如果您有不同的显示类别,例如“第 1 步是红-黄-绿,但第 2 步只是红-绿,第 3 步是红-粉-橙”(或者如果您相信自己会),我会将颜色移到他们自己的表中,并创建一个带有状态 ID、颜色 ID 和最大时间的状态-颜色桥表。不过,这使得检索变得更加复杂。
现在,如果每个状态确实有多个活动,那么我会将状态变成与活动的父子关系,而不是像现在使用规则那样的多对多关系。因此状态将具有名称,而活动将如下所示:
在您的主对象上,您实际上会持有活动 ID 而不是状态 ID,因为您可以从活动中获取状态。
我要做的另一件事是删除规则表。唯一需要规则表的情况是,如果您有多个状态、多个活动,并且它们之间存在多种关系(例如,新状态和已关闭状态都能够执行分配车辆活动)。根据您的示例,情况似乎并非如此。如果这种关系与您的示例不同,那么您实际上可能会在活动和状态之间建立这种多对多关系。在这种情况下,您的规则表看起来不错,但需要注意的是您不需要红色限制。
顺便说一句,我强烈建议您将实际的工作流逻辑放在存储过程中,无论您是保持线性流(就像现在这样)还是转向非线性工作流模型。您可以使用触发器的组合和检查约束,迫使工作流以特定的方式来操作,但它是一个很多更容易理解,如果你只是做一个存储过程:所有的代码是在一个地方不容易- 忘记区域就像一个触发器。把它放在一个存储过程中也将它从应用程序和业务对象层抽象出来,所以他们只需要调用一个方法,说“转到下一个工作流步骤”(并且可能传递一个细节来帮助你找出哪个工作流步骤,如果这不是一个线性过程)。
编辑(发布问题更新)
根据您的问题更新和评论,我可以使用三表方法。我不确定您是否需要它,但这可以简化应用程序级别的事情。
此时,您拥有的是一个状态机,带有一个 State(状态)表和一个 Transition(活动)表。然后您的规则表定义哪些转换对特定状态有效。
我会稍微更改规则表,如下所示:
有一个小的变化:不同键的位置。您的规则表现在读起来就像一本书:从一个状态开始,执行转换并以不同的状态结束(或相同的状态 - 您有一个最终状态与初始状态相同的示例)。
您将对起始状态 ID 和活动 ID 具有唯一键约束,以确保从特定状态的特定转换始终以单个状态结束。
在您的车辆表上,我会使用 idRule 而不是 idStatus,以便轻松判断您需要哪组限制。您可能还需要一个显示车辆 ID、规则 ID 和添加时间的历史记录表,以便您可以跟踪工作流中发生的情况。
这意味着您的“转到下一个工作流程步骤”存储过程实际上非常简单:给定车辆 ID 和要执行的活动,您可以对规则表进行快速选择,以查看是否存在从车辆规则的有效转换通过您在 proc 中获得的活动 ID 进行状态。如果有,执行该转换:相应地更新车辆表(设置 idRule 和 LastUpdate);如果没有,则返回一个错误,表明一定出了问题。
将带有两个外键的表返回到另一个表也没有问题。idCurrentState 和 idNextState 都可以是返回 State 的合法外键。您只需要两个外键的不同名称(例如,FK_Rule_State_CurrentState 和 FK_Rule_State_NextState)。