C# 工作流设计困境-状态机,是或否
我是WF的初学者,但我读过一本书,也做过很多谷歌搜索。我想写一个库存管理服务。库存由具有以下状态的单个项目组成:C# 工作流设计困境-状态机,是或否,c#,.net,workflow,workflow-foundation,C#,.net,Workflow,Workflow Foundation,我是WF的初学者,但我读过一本书,也做过很多谷歌搜索。我想写一个库存管理服务。库存由具有以下状态的单个项目组成: 备用 安装 修复中 物品可能在每个州停留数月,并且有数千件物品 问题是,我是否为所有不同的状态创建状态机工作流?或者我要创建用于在状态之间转换的工作流 如果我理解正确,如果我创建一个单一的状态机工作流,那么每个项目都将始终运行一个工作流。这意味着成千上万的工作流程一直在运行。此外,我还需要能够显示每个项目状态的快照,这意味着我必须以某种方式查询所有工作流的当前状态,或者在每个状态转换
<强>赏金赢家:毛里斯 -感谢所有其他人真正帮助我更多地了解工作流、MS工作流基础和其他更轻量级的替代品。不幸的是,赏金赢家只能有一个,莫里斯的回答及其评论对我帮助最大。
尽管状态机模式在技术上是正确的选择,但也有一个选项可以创建带有一个巨大循环的顺序工作流。在某些情况下,它实际上工作得更好,更容易理解。您有三种不同的状态,就我所见,所有转换都是允许的。考虑到这一点,我不会为状态机而烦恼,因为状态机是一段检查允许的转换并向前推进的代码 当状态驱动业务时,或者当需要一段受信任的代码作为负责“有效转换”的唯一参与者时,状态机是有意义的更简单地说,您只需要在任何时间点具有给定状态的实体…Aviad,我同意您的意见,即工作流应该在状态之间。正在盘点的零件的状态听起来像是项目的状态/属性。该状态几乎可以以任何方式存储(例如数据库、文件…),因为项目在状态之间的移动将存在于业务逻辑层中 听起来像是一个有趣的项目,祝你好运。考虑到你添加的内容(超过3个州,并非所有的转换都允许),我将执行以下操作:
这很容易做到:向类中添加成员或向表中添加列等,其他人在其帖子/评论中已经提到了这一点
然后,您所需要做的就是使用状态机转换您的项目,每当发生外部事件时,这就强制/暗示了这一点。不确定工作流是否是您首先要寻找的 工作流是发生的某种业务流程。这意味着这个过程的开始和结束。您的描述听起来更像是在跟踪库存中的物品 当项目更改状态时,工作流听起来更合适。例如,当一个项目已安装并发生故障,需要修复时,您将启动一个工作流,以将该零件更换为工作零件,将损坏的零件发送给维修人员,最后将其作为固定备件送回仓库。工作流将描述此过程,并从项目损坏的报告开始,以项目修复或丢弃和更换结束 最后一个工作流很可能是一个状态工作流,因为该项目经历了以下各个阶段:
- 断断续续
- 破损和更换
- 在商店里修理
- 修复
- 等
- 好的。让我们看看我能不能帮你。让我们从设计开始:
设计一个状态机和一个工作流是有意义的。这两种观点只是对你的问题的不同看法,从不同的角度揭示了一些问题。事实上,经常发生的情况是,对工作流不熟悉的开发人员设计状态机而不是工作流流程。工作流流程视图主要切换图表中方框和转换的角色:方框是可以更改状态的活动-在转换时,工作项可以进入新状态(好的,这在科学上不正确,但可能有帮助:-)
对我来说,状态机方面似乎更重要。因此,将您的软件实现为状态机
是的,您应该使数据库中的所有项持久化。这也是保持长时间运行的工作流运行的方式——它们一直存在于数据库中,直到被任何活动重新激活。所有现成的业务流程管理系统(BPMS)都是这样做的。这些工作流不会保存在内存中
将所有内容都保存在数据库中,可以轻松创建报告
正如其他人已经提到的,用状态信息创建一个新列,甚至用元数据创建一个新表:state,可能是状态改变时的日志,谁改变了状态,关于即将发生的事件的信息(零件已订购但未交付-如果交付丢失,应在多少天后与供应商进行检查?)。这将使您有机会根据需要添加元数据
var phoneCall = new StateMachine<State, Trigger>(State.OffHook);
phoneCall.Configure(State.OffHook)
.Permit(Trigger.CallDialed, State.Ringing);
phoneCall.Configure(State.Ringing)
.Permit(Trigger.HungUp, State.OffHook)
.Permit(Trigger.CallConnected, State.Connected);
phoneCall.Configure(State.Connected)
.OnEntry(() => StartCallTimer())
.OnExit(() => StopCallTimer())
.Permit(Trigger.LeftMessage, State.OffHook)
.Permit(Trigger.HungUp, State.OffHook)
.Permit(Trigger.PlacedOnHold, State.OnHold);
// ...
phoneCall.Fire(Trigger.CallDialled);
Assert.AreEqual(State.Ringing, phoneCall.State);
var stateMachine = new StateMachine<State, Trigger>(
() => myState.Value,
s => myState.Value = s);