你知道我要说什么的,当这个世界被XML符号标识后,我一直尽力向它靠拢。面向对象数据库都出现了,我还能不好好学习学习XML吗?
今天要说的如何将储存在Captaris Workflow 6.0工作流平台数据库中的业务数据保存到另一个业务系统中。
如大家所知,一个系统与另一个系统最难的就是交互,就算是使用XML这种通用、跨平台的方式也意味着添加或修改现有的接口。不幸的是,做为一个工作流系统,必须要具有这样的能力。为了满足这样的需求,大部分(包括Captaris)工作流平台都或多或少地使用了XML技术,以能对外宣称:“我的平台能跨越N个操作系统,支持N种交互方式”。
闲话少说,言归正传。Captaris Workflow 6.0的模型、流程实例的数据都以XML方式储存在SQL Server 2005的数据库中,常见的格式如下:
1<Common>
2 <ModelData>
3 <ApprovedTasks />
4 <RejectTask />
5 <IsApproved />
6 <!--选择的技术/产品会签者-->
7 <ProductResponseID />
8 <!--连接外部数据库字符串-->
9 <ConnectionString>Data Source=(local);Initial Catalog=WorkflowExtension;Integrated Security=True</ConnectionString>
10 </ModelData>
11 <PCOrderData>
12 <ProcessID />
13 <PCNO />
14 <ECRNO />
15 <FileNO />
16 <TotalNO />
17 <PCName />
18 <TotalName />
19 <ChangedCategoris />
20 <ChangedType />
21 <ChangedReason />
22 <RequestDate />
23 <InproduceIdea />
24 <producedIdea />
25 <SendPIdea />
26 <!--需要验证-->
27 <IsValidated>0</IsValidated>
28 <ChangedCategorisTxt />
29 <!--总图号-->
30 <DrawNO />
31 <!--总图名称-->
32 <DrawName />
33 <!--清单文件存放目录-->
34 <FileUrl />
35 <!--提交人需要更改的文件和完成日期-->
36 <SubmitRelatedFile />
37 </PCOrderData>
38 <SubmitData>
39 <!--存放执行人的ID-->
40 <ResponsibleID />
41 <!--提交者姓名-->
42 <SubmitName />
43 <!--需要验证-->
44 <IsValidated>0</IsValidated>
45 <FileName />
46 <!--技术文件-->
47 <ComDate />
48 <!--预计完成日期-->
49 <PlanComTime />
50 <!--实际完成日期-->
51 <FactComTime />
52 </SubmitData>
53 <TogetherPC>
54 <!--共同实施的PC-->
55 </TogetherPC>
56</Common>
Captaris提供了很多种常见的与外部系统交互的功能(Action):
- WebService请求或响应;
- 文件系统监视;
- BizTalk事件;
- SharePoint事件;
- …
遗憾的是没有提供对数据记录的事件响应,流程分析人员在把流程模型交给流程开发人员(IT)后,流程开发人员就要面临如何将工作流与各种业务系统连接起来,如人员招聘流程结束后如何反应到HR系统中,或费用报销流程结束后如何反应到财务系统中甚至反应到商业行为控制系统中(如果费用中包含礼品、应酬等费用时)。通常可用的连接方式如下:
- 通过WebService把记录插入到业务系统,或更新业务系统中的数据;(业务逻辑级别交互)
- 将记录直接插入到业务系统的数据库;(数据库级别交互,这种方式是我用得最多的了)
- 通过Windows服务将记录插入到业务系统;可使用WebService、数据库直接交互、MSMQ…
前两种方式都是即席(同步)的操作,Windows服务前两种方式的基础上添加了异步操作的特性,使得系统性能和执行效率得以提升。
不管是使用WebService还是数据库直接交互(特别是数据库直接交互),流程开发人员都要面临从Teamplate数据库中取得并分解业务数据,以符合WebService或业务系统数据库的接口要求。
SQL Server 2005原生支持XML。因此,可以通过Xquery来直接操作XML,就象SQL Server 2000中的OPENXML一样。只是在性能和效率上(特别是吃内存)提升得非非非常大。
示例如下:
2 set QUOTED_IDENTIFIER ON
3 go
4
5
6 -- =============================================
7 -- Author: < 蒋勇星 >
8 -- Create date: < 2006 - 12 - 25 >
9 -- Description: < 从Teamplate数据库中检索 " 产品更改单数据 " >
10 -- =============================================
11 ALTER PROCEDURE [dbo].[FetchProductChangeByPID]
12 -- Add the parameters for the stored procedure here
13 @PID INT -- 流程编号
14 AS
15 BEGIN
16 -- SET NOCOUNT ON added to prevent extra result sets from
17 -- interfering with SELECT statements.
18 SET NOCOUNT ON;
19
20 DECLARE @xmlOfFormData XML -- 承载 " Common " 字段的XML变量,包含PC单的基本信息
21 DECLARE @xmlOfSignature XML -- 承载 " SignData " 字段的XML变量,包含PC单的签署信息
22 DECLARE @FORMXMLNAME NVARCHAR( 20 )
23 DECLARE @SIGNATUREXMLNAME AS NVARCHAR( 20 )
24 DECLARE @PCNO NVARCHAR( 16 )
25 DECLARE @FILENO NVARCHAR( 100 )
26 DECLARE @PCNAME NVARCHAR( 200 )
27 DECLARE @CHANGECATEGORIES INT
28 DECLARE @CHANGETYPE INT
29 DECLARE @CHANGEDREASON NVARCHAR( 300 )
30 DECLARE @REQUESTDATE DATETIME
31 DECLARE @INPRODUCECOMMENT NVARCHAR( 200 )
32 DECLARE @PRODUCINGCOMMENT NVARCHAR( 200 )
33 DECLARE @SENDPCOMMENT NVARCHAR( 200 )
34 DECLARE @NEEDVALIDATE INT
35 DECLARE @CHNGCATEGORYEXT NVARCHAR( 20 )
36 DECLARE @AFFECTEDPC NVARCHAR( 100 )
37 DECLARE @PLANCOMTIME DATETIME
38 DECLARE @FACTCOMTIME DATETIME
39
40 SELECT @FORMXMLNAME = ' Common '
41 SELECT @SIGNATUREXMLNAME = ' SignData '
42 -- 查询PROCESSDATA表中的 ' Common ' 字段,给@xmlOfFormData赋值
43 SELECT @xmlOfFormData = [DATA]
44 FROM [Teamplate].[dbo].[PROCESSDATA]
45 WHERE([PID] = @PID AND
46 [NAME] = @FORMXMLNAME)
47 -- 查询PROCESSDATA表中的 ' SignData ' 字段,给@xmlOfSignature赋值
48 SELECT @xmlOfSignature = [DATA]
49 FROM [Teamplate].[dbo].[PROCESSDATA]
50 WHERE([PID] = @PID AND
51 [NAME] = @SIGNATUREXMLNAME)
52 -- 分解XML并赋值到变量中
53 SELECT
54 @PID = Table1.Column1.value( ' (/Common/PCOrderData/ProcessID)[1] ' , ' int ' ),
55 @PCNO = Table1.Column1.value( ' (/Common/PCOrderData/PCNO)[1] ' , ' nvarchar(16) ' ),
56 @FILENO = Table1.Column1.value( ' (/Common/PCOrderData/FileNO)[1] ' , ' nvarchar(100) ' ),
57 @CHANGECATEGORIES = Table1.Column1.value( ' (/Common/PCOrderData/ChangedCategoris)[1] ' , ' int ' ),
58 @CHANGETYPE = Table1.Column1.value( ' (/Common/PCOrderData/ChangedType)[1] ' , ' int ' ),
59 @CHANGEDREASON = Table1.Column1.value( ' (/Common/PCOrderData/ChangedReason)[1] ' , ' nvarchar(200) ' ),
60 @REQUESTDATE = Table1.Column1.value( ' (/Common/PCOrderData/RequestDate)[1] ' , ' datetime ' ),
61 @INPRODUCECOMMENT = Table1.Column1.value( ' (/Common/PCOrderData/InproduceIdea)[1] ' , ' nvarchar(200) ' ),
62 @PRODUCINGCOMMENT = Table1.Column1.value( ' (/Common/PCOrderData/producedIdea)[1] ' , ' nvarchar(200) ' ),
63 @SENDPCOMMENT = Table1.Column1.value( ' (/Common/PCOrderData/SendPIdea)[1] ' , ' nvarchar(200) ' ),
64 @NEEDVALIDATE = Table1.Column1.value( ' (/Common/PCOrderData/IsValidated)[1] ' , ' int ' ),
65 @CHNGCATEGORYEXT = Table1.Column1.value( ' (/Common/PCOrderData/ChangedCategorisTxt)[1] ' , ' nvarchar(20) ' ),
66 @AFFECTEDPC = Table1.Column1.value( ' (/Common/TogetherPC)[1] ' , ' nvarchar(200) ' ),
67 @PLANCOMTIME = Table1.Column1.value( ' (/Common/SubmitData/PlanComTime)[1] ' , ' datetime ' ),
68 @FACTCOMTIME = Table1.Column1.value( ' (/Common/SubmitData/FactComTime)[1] ' , ' datetime ' )
69 FROM
70 @xmlOfFormData.nodes( ' /Common ' ) AS Table1(Column1)
71
72
73 SELECT @PID AS [PID],
74 @PCNO AS [PCNO],
75 @FILENO AS [FILENO],
76 @CHANGECATEGORIES AS [CHANGECATEGORIES],
77 @CHANGETYPE AS [CHANGETYPE ],
78 @CHANGEDREASON AS [CHANGEDREASON],
79 @REQUESTDATE AS [REQUESTDATE],
80 @INPRODUCECOMMENT AS [INPRODUCECOMMENT],
81 @PRODUCINGCOMMENT AS [PRODUCINGCOMMENT],
82 @SENDPCOMMENT AS [SENDPCOMMENT],
83 @NEEDVALIDATE AS [NEEDVALIDATE],
84 @CHNGCATEGORYEXT AS [CHNGCATEGORYEXT],
85 @AFFECTEDPC AS [AFFECTEDPC],
86 @PLANCOMTIME AS [PLANCOMTIME],
87 @FACTCOMTIME AS [FACTCOMTIME]
88 END
套用最近流行的一句话:球进了…他不是一个人…