前言
代码源码不重要,重要的是思想!
本工作流基于了自主研发的ORM层、数据库同步层;实现了分布式环境下的工作流协同操作。
本工作流设计遵循以下原则:
1. 工作流基于.net DataTable模型,一切围绕这个DataTable展开;因为。net在界面很多的绑定都支持了datatable。
2. 工作流模型只负责状态的维护,不负责状态的扭转。即:每天下午4点新建订单转为失效订单 这种处理不属于工作流范畴,而是属于业务调度系统,是另外一个框架。
Pixysoft.Framework.Workflow 正文
ER图:
工作流框架包括了 工作流设计对象、工作流实例对象 两大类。
1. 工作流设计对象 帮助用户自行设计一套包含表单、所有状态、状态默认扭转关系的对象。
2. 工作流实例对象 是根据用户设计好的工作流去生成实例调用。
同时说明一些设计要点:
1. WfFormSchema是表单设计对象,支持主从表的设计(就是一种自引用)
2. WfStatus是状态设计对象,包含了用户自定义的各种状态。
3. WfProjectHistory是记录工作流实例对象 状态扭转 的历史记录。
代码演示
创建一个工作流:
//
新建工作流的主表单schema
DataTable maintb
=
new
DataTable(
"
POS_ITEMDISTRIBUTION
"
);
maintb.Columns.Add(
"
BILLCODE
"
);
maintb.Columns.Add(
"
CREATEDATE
"
);
maintb.Columns.Add(
"
MERCHANTCODE
"
);
maintb.Columns.Add(
"
BOXLOCATIONCODE
"
);
maintb.Columns.Add(
"
USRBOXCODE
"
);
maintb.Columns.Add(
"
STATUS
"
);
maintb.Columns.Add(
"
SHOPCODE
"
);
//
新建工作流的子表单 schema
DataTable subtb
=
new
DataTable(
"
POS_ITEMDISTRIBUTIONDETAIL
"
);
subtb.Columns.Add(
"
BILLCODE
"
);
subtb.Columns.Add(
"
ITEMTYPENAME
"
);
subtb.Columns.Add(
"
INPUTPRICE
"
);
subtb.Columns.Add(
"
INPUTQTY
"
);
subtb.Columns.Add(
"
REMARK
"
);
subtb.Columns.Add(
"
ITEMNAME
"
);
subtb.Columns.Add(
"
ITEMTYPECODE
"
);
subtb.Columns.Add(
"
BARCODE
"
);
subtb.Columns.Add(
"
ISNEW
"
);
subtb.Columns.Add(
"
ITEMCODE
"
);
subtb.Columns.Add(
"
COMMISSION
"
);
subtb.Columns.Add(
"
STAFFCOMMISSION
"
);
subtb.Columns.Add(
"
ID
"
);
//
获取工作流对象
IWorkflowManager manager
=
WorkflowManager.Instance;
//
获取设计对象
IWorkflowDesigner designer
=
manager.GetDesigner();
//
创建一个名为POS_ITEMDISTRIBUTION的工作流(配货单)主表单为上文主表
WfProjectSchema project
=
designer.CreateProject(
"
POS_ITEMDISTRIBUTION
"
,
"
POS_ITEMDISTRIBUTION
"
,
"
BILLCODE
"
, maintb);
//
工作流主表配置自定义搜索的关键字
designer.AddFormKeyValue(project.FormSchema,
"
BILLCODE
"
);
designer.AddFormKeyValue(project.FormSchema,
"
MERCHANTCODE
"
);
designer.AddFormKeyValue(project.FormSchema,
"
USRBOXCODE
"
);
//
根据上文schema创建工作流的子表单
WfFormSchema subform
=
designer.CreateSubForm(project.FormSchema,
"
POS_ITEMDISTRIBUTIONDETAIL
"
,
"
ID
"
, subtb);
//
创建工作流的状态
WfStatus a001
=
designer.CreateStartStatus(project,
"
NEW
"
);
WfStatus a002
=
designer.CreateNextStatus(project, a001,
"
CHECKED
"
);
WfStatus a003
=
designer.CreateNextStatus(project, a002,
"
ABNOMITY
"
);
WfStatus a004
=
designer.CreateNextStatus(project, a003,
"
REJECTED
"
);
WfStatus a005
=
designer.CreateNextStatus(project, a004,
"
PROCESSED
"
);
WfStatus a006
=
designer.CreateNextStatus(project, a005,
"
PASSED
"
);
//
确认设计
designer.Commit();
新建工作流实例代码:
//
获取工作流管理者
IWorkflowManager manager
=
WorkflowManager.Instance;
//
获取表单的对象
DataTable table
=
manager.GetProjectTable(
"
POS_ITEMDISTRIBUTION
"
);
//
获取子表单对象
DataTable subtable
=
manager.GetProjectSubTable(
"
POS_ITEMDISTRIBUTION
"
);
//
处理表单数据
DataRow row
=
table.NewRow();
row[
"
CREATEDATE
"
]
=
DateTime.Now;
row[
"
MERCHANTCODE
"
]
=
"
123123123
"
;
row[
"
BOXLOCATIONCODE
"
]
=
"
I0506
"
;
row[
"
USRBOXCODE
"
]
=
"
00154
"
;
row[
"
STATUS
"
]
=
"
NEW
"
;
row[
"
SHOPCODE
"
]
=
"
001
"
;
table.Rows.Add(row);
//
处理子表单数据
DataRow subrow
=
subtable.NewRow();
subrow[
"
INPUTPRICE
"
]
=
100
;
subrow[
"
INPUTQTY
"
]
=
1
;
subrow[
"
ITEMNAME
"
]
=
"
hello
"
;
subrow[
"
ITEMTYPECODE
"
]
=
"
12312
"
;
subrow[
"
BARCODE
"
]
=
"
101540001125
"
;
subrow[
"
ISNEW
"
]
=
false
;
subrow[
"
ITEMCODE
"
]
=
"
123123123
"
;
subrow[
"
COMMISSION
"
]
=
0.02
;
subrow[
"
STAFFCOMMISSION
"
]
=
0.02
;
subtable.Rows.Add(subrow);
//
根据工作流名称创建一个新的工作流
IWorkflowProject project
=
manager.CreateProject(
"
POS_ITEMDISTRIBUTION
"
);
//
根据已经输入的表单创建工作流的表单
IWorkflowForm form
=
project.CreateForm(table);
//
根据已经输入的子表单创建工作流的子表单
IWfFormCollection subforms
=
form.CreateSubForms(subtable);
//
工作流确认
project.Commit();
工作流状态扭转:
IWorkflowManager manager
=
WorkflowManager.Instance;
//
搜索状态为new的工作流
IWfProjectCollection projects
=
manager.SearchProjects(
"
POS_ITEMDISTRIBUTION
"
,
"
NEW
"
);
if
(projects.Count
==
0
)
return
;
//
工作流对象转化为Datatable
DataTable projecttb
=
projects.ToTable();
//
获取第0行的工作流对象的datarow
DataRow projectrow
=
projecttb.Rows[
0
];
//
根据datarow获取对应的工作流
IWorkflowProject project
=
projects[projecttb.Rows.IndexOf(projectrow)];
//
状态扭转
while
(project.HasNext())
{
//
获取工作流的表单
IWorkflowForm form
=
project.GetForm();
//
获取工作流表单对应的datatable
DataTable maintb
=
form.ToTable();
//
可以自行修改表单数据 例如绑定界面等
//
更新表单数据
form.Update(maintb);
//
获取表单对应的子表单
IWfFormCollection subforms
=
form.GetSubForms();
//
获取子表单对应的datatable
DataTable subformtables
=
subforms.ToTables();
//
可以自行修改子表单数据 例如绑定界面等
//
更新子表单数据
subforms.Update(subformtables);
//
转移到默认下个状态
project.ToNext(
null
);
}
//
确认操作
project.Commit();
后续
本工作流技术算是比较落后,不支持众多牛人关于扭转的算法。
个人觉得,状态扭转用代码实现是最方便的。当然,部分扭转是可以抽象成为一定的框架,例如BPEL之类的规范;变成各种时间调度、事件驱动调度等算法。但是这个如果和工作流本身的状态管理绑定在一起,就非常的不方便。
我相信用过所谓开源、0代码工作流的兄弟,一定厌倦那种xml的描述、厌倦用界面拖拖拉拉写企业代码。程序员怎么就变成了个二流的操作人员?这个是个误区,是过份夸大了xml的误区。
微软的workflow foundation是个不错的升华,重新把企业编程的权利转移给了程序员。
至于刚才所说的BPEL、时间调度算法等,我会在下一个框架实现,基于了本工作流的模型,下一个框架就叫
Pixysoft.Framework.Schedular
最后说一句,设计任何框架的目的:当然是以易用为主!