第五章 工作流定义工具的设计与实现(三)
2012-09-18 15:04
281 查看
5.7 开发工作流图形定义工具
5.7.2 项目配置文件
配置文件app.config中包含了数据库的连接配置:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
......
<add key="DBsqlConn" value="data source=(local);initial catalog=myworkflow;
password=mxh;user id=mxh;persist security info=True;"/>
</appSettings>
</configuration>
5.7.3 数据库操作代码文件
与工作流引擎的实现类似,为了增强数据访问的安全性,提高代码编写效率,这里也把对数据库的操作封装在类文件DataAccess.cs中。因为数据访问操作代码与第四章工作流引擎的数据访问基础类Base类似,这里仅列举数据访问操作的部分函数名:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
namespace drawtaskbytoolbar
{
public class DataAccess
{
private SqlConnection mAppCon = null;
private string SqlErrDes = "";
public DataAccess()
{
mAppCon = new SqlConnection();
string connstring = ConfigurationSettings.AppSettings["DBsqlConn"];
mAppCon.ConnectionString = connstring;
}
//返回数据库操作异常的公共变量
public string BaseSqlErrDes
{
get
{
return SqlErrDes;
}
}
......
//以sql语句为参数,执行sql修改、添加、删除操作
public bool SQLExeNonQuery( string Sql )
......
//以sql命令对象为参数,执行删除、添加、修改等操作
public bool SQLExeNonQuery( SqlCommand cmd )
//执行事务处理(多语句修改、添加、删除操作)
public bool ExeSQLNonQueryTransaction( string Sql )
......
//sql语句查询,返回dataset
public DataSet SQLExeDataSet(string Sql)
......
//sql语句查询,返回dataset
public DataSet SQLExeDataSet(SqlCommand cmd)
......
//判断是否存在记录
public bool IfExistRecord(SqlCommand cmd)
......
//获取任务定义的编号
public string GetTaskID(string processid,string taskname)
{
string strSql="select TaskID from TaskDefinition where
ProcessID="+processid+" and TaskName='"+taskname+"'";
......
}
}
}
5.7.4 节点定义类文件
1、节点定义类文件NodeClass.cs
using System;
using System.Drawing;
namespace drawtaskbytoolbar
{
public class NodeClass
{
//节点矩形框的左上角坐标,用于定位节点图形
public float LeftTopX;
public float LeftTopY;
//节点矩形的宽度和长度(单位像素)
public int Width;
public int Height;
//节点名称
public string NodeName;
//节点类型(枚举类型变量,后面有定义)
public nodetypedefine NodeType;
//节点的过程逻辑属性(如“AndJoin”,表示并行连接)
public string ProcessLogic="";
//构造函数
public NodeClass()
{
LeftTopX=-1;
LeftTopY=-1;
}
public NodeClass(float x,float y)
{
LeftTopX=x;
LeftTopY=y;
}
//判断是否同一节点
public bool IsSameNode(NodeClass node)
{
if((int)this.LeftTopX == (int)node.LeftTopX & (int)this.LeftTopY
== (int)node.LeftTopY & this.NodeName == node.NodeName)
return true;
else
return false;
}
//判断鼠标点击位置是否在当前节点框内
public bool IsPointInNode(float x,float y)
{
if(x >= this.LeftTopX & y>=this.LeftTopY & x<=this.LeftTopX+this.Width
& y<=this.LeftTopY+this.Height)
return true;
else
return false;
}
}
//记录节点类型的枚举类型定义
public enum nodetypedefine
{
notask=0,start,end,tasknode,andsplit,orsplit,andjoin,orjoin,transition
}
}
2、保存节点集的集合类NodeRecords.cs
using System;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
namespace drawtaskbytoolbar
{
public class NodeRecords
{
//保存所画节点的对象数组
public ArrayList nodeList=new ArrayList();
//空构造函数
public NodeRecords(){}
//添加节点
public bool AddNode(NodeClass node)
{
nodeList.Add(node);
return true;
}
//删除节点
public bool DeleteNode(NodeClass node)
{
for(int i=0;i<nodeList.Count;i++)
{
//节点名称唯一
if(((NodeClass)nodeList[i]).NodeName == node.NodeName)
{
nodeList.RemoveAt(i);
return true;
}
}
return false;
}
//公共属性(节点元素个数)
public int Count
{
get
{
return nodeList.Count;
}
}
//获取节点数组的第i个节点对象
public NodeClass GetNode(int i)
{
if(i>=0 & i<Count)
return (NodeClass)nodeList[i];
else
return null;
}
//根据节点名称获取节点
public NodeClass GetNode(string nodename)
{
for(int i=0;i<nodeList.Count;i++)
{
if(GetNode(i).NodeName == nodename)
return GetNode(i);
}
return null;
}
//判断节点数组中是否包含给定类型的节点
public bool HasNode(nodetypedefine nodetype)
{
for(int i=0;i<nodeList.Count;i++)
{
if(GetNode(i).NodeType == nodetype)
return true;
}
return false;
}
//新增加的节点命名为“任务k”,k始终不大于节点数,每删除或重命名一个,就产生一个
//可重复使用的节点名“任务j”,j<=节点总数,这样就可以把新增加的节点命名为“任务
//j”。这样可以始终保持节点名称的唯一。
//获取新增节点的默认名称
public string GetNewNodeName()
{
string nodename="";
int j=0;
for(int i=1;i<=nodeList.Count+1;i++)
{
nodename="任务"+i;
//在节点集合中找名称为任务i的节点
for(j=0;j<nodeList.Count;j++)
{
if(((NodeClass)nodeList[j]).NodeName == nodename)
break;
}
//如果找不到就退出外层循环,新增节点命名为任务i.否则继续循环.
if(j == nodeList.Count)
break;
}
//如果内外循环都被完整执行,则nodename为"任务"+(nodeList.Count+1)
return nodename;
}
//获取新的逻辑节点名称(保证逻辑节点名称的唯一性)
public string GetNewLogicNodeName(nodetypedefine nodetype)
{
string nodename="";
int j=0;
for(int i=1;i<=nodeList.Count+1;i++)
{
if(nodetype == nodetypedefine.andsplit)
nodename="And Split"+i;
if(nodetype == nodetypedefine.andjoin)
nodename="And Join"+i;
if(nodetype == nodetypedefine.orsplit)
nodename="Or Split"+i;
if(nodetype == nodetypedefine.orjoin)
nodename="Or Join"+i;
//在节点集合中找名称为任务i的节点
for(j=0;j<nodeList.Count;j++)
{
if(((NodeClass)nodeList[j]).NodeName == nodename)
break;
}
//如果找不到就退出外层循环,新增节点命名为任务i.否则继续循环.
if(j == nodeList.Count)
break;
}
//如果内外循环都被完整执行,则nodename为"任务"+(nodeList.Count+1)
return nodename;
}
//保存开始、结束及任务节点到数据库(使用带参数的sql命令是为了增加安全性)
public int SaveProcess(string processname,string tablename,string tablealias,
string identityfield,string
duedate)
{
string strSql"insert into ProcessDefinition(ProcessName,RelatedTable,
Alias,IdentifiedField,DueDate) values(@ProcessName,'"+tablename
+"','"+tablealias+"','"+identityfield+"',@DueDate)";
SqlCommand cmd;
try
{
cmd=new SqlCommand(strSql);
cmd.Parameters.Add("@ProcessName",SqlDbType.VarChar,50);
cmd.Parameters["@ProcessName"].Value=processname;
cmd.Parameters.Add("@DueDate",SqlDbType.SmallInt);
cmd.Parameters["@DueDate"].Value=int.Parse(duedate);
}
catch(System.FormatException ex)
{
MessageBox.Show("数据格式错误!");
return -1;
}
DataAccess database=new DataAccess();
if(! database.SQLExeNonQuery(cmd))
{
MessageBox.Show("保存流程失败!");
return -1;
}
//获取流程编号
strSql="select ProcessID from ProcessDefinition where ProcessName
= @ProcessName"
cmd=new SqlCommand(strSql);
cmd.Parameters.Add("@ProcessName",SqlDbType.VarChar,50);
cmd.Parameters["@ProcessName"].Value=processname;
DataSet ds=database.SQLExeDataSet(cmd);
string processID=ds.Tables[0].Rows[0]["ProcessID"].ToString();
//保存所有节点(包括节点名称、节点类型、任务节点包含的过程逻辑等)
string completeSql="";
for(int i=0;i<Count;i++)
{
//保存开始节点
if(GetNode(i).NodeType == nodetypedefine.start)
completeSql=completeSql+"insert into TaskDefinition
(ProcessID,TaskName,NodeType) values("+processID+",'"
+GetNode(i).NodeName+"','Start');";
//保存结束节点
if(GetNode(i).NodeType == nodetypedefine.end)
completeSql=completeSql+"insert into TaskDefinition
(ProcessID,TaskName,NodeType) values("+processID+",'"
+GetNode(i).NodeName+"','End');";
//保存任务节点
if(GetNode(i).NodeType == nodetypedefine.tasknode)
completeSql=completeSql+"insert into TaskDefinition
(ProcessID,TaskName,NodeType,ProcessLogic) values
("+processID+",'"+GetNode(i).NodeName+"','TaskNode','"
+GetNode(i).ProcessLogic+"');";
}
if(completeSql == "")
{
MessageBox.Show("没有可保存的节点!");
return -1;
}
//执行sql事务处理,保证节点保存操作的完整性
if(! database.ExeSQLNonQueryTransaction(completeSql))
{
MessageBox.Show("保存节点失败!"+database.BaseSqlErrDes);
return -1;
}
return int.Parse(processID);
}
}
}
5.7.2 项目配置文件
配置文件app.config中包含了数据库的连接配置:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
......
<add key="DBsqlConn" value="data source=(local);initial catalog=myworkflow;
password=mxh;user id=mxh;persist security info=True;"/>
</appSettings>
</configuration>
5.7.3 数据库操作代码文件
与工作流引擎的实现类似,为了增强数据访问的安全性,提高代码编写效率,这里也把对数据库的操作封装在类文件DataAccess.cs中。因为数据访问操作代码与第四章工作流引擎的数据访问基础类Base类似,这里仅列举数据访问操作的部分函数名:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
namespace drawtaskbytoolbar
{
public class DataAccess
{
private SqlConnection mAppCon = null;
private string SqlErrDes = "";
public DataAccess()
{
mAppCon = new SqlConnection();
string connstring = ConfigurationSettings.AppSettings["DBsqlConn"];
mAppCon.ConnectionString = connstring;
}
//返回数据库操作异常的公共变量
public string BaseSqlErrDes
{
get
{
return SqlErrDes;
}
}
......
//以sql语句为参数,执行sql修改、添加、删除操作
public bool SQLExeNonQuery( string Sql )
......
//以sql命令对象为参数,执行删除、添加、修改等操作
public bool SQLExeNonQuery( SqlCommand cmd )
//执行事务处理(多语句修改、添加、删除操作)
public bool ExeSQLNonQueryTransaction( string Sql )
......
//sql语句查询,返回dataset
public DataSet SQLExeDataSet(string Sql)
......
//sql语句查询,返回dataset
public DataSet SQLExeDataSet(SqlCommand cmd)
......
//判断是否存在记录
public bool IfExistRecord(SqlCommand cmd)
......
//获取任务定义的编号
public string GetTaskID(string processid,string taskname)
{
string strSql="select TaskID from TaskDefinition where
ProcessID="+processid+" and TaskName='"+taskname+"'";
......
}
}
}
5.7.4 节点定义类文件
1、节点定义类文件NodeClass.cs
using System;
using System.Drawing;
namespace drawtaskbytoolbar
{
public class NodeClass
{
//节点矩形框的左上角坐标,用于定位节点图形
public float LeftTopX;
public float LeftTopY;
//节点矩形的宽度和长度(单位像素)
public int Width;
public int Height;
//节点名称
public string NodeName;
//节点类型(枚举类型变量,后面有定义)
public nodetypedefine NodeType;
//节点的过程逻辑属性(如“AndJoin”,表示并行连接)
public string ProcessLogic="";
//构造函数
public NodeClass()
{
LeftTopX=-1;
LeftTopY=-1;
}
public NodeClass(float x,float y)
{
LeftTopX=x;
LeftTopY=y;
}
//判断是否同一节点
public bool IsSameNode(NodeClass node)
{
if((int)this.LeftTopX == (int)node.LeftTopX & (int)this.LeftTopY
== (int)node.LeftTopY & this.NodeName == node.NodeName)
return true;
else
return false;
}
//判断鼠标点击位置是否在当前节点框内
public bool IsPointInNode(float x,float y)
{
if(x >= this.LeftTopX & y>=this.LeftTopY & x<=this.LeftTopX+this.Width
& y<=this.LeftTopY+this.Height)
return true;
else
return false;
}
}
//记录节点类型的枚举类型定义
public enum nodetypedefine
{
notask=0,start,end,tasknode,andsplit,orsplit,andjoin,orjoin,transition
}
}
2、保存节点集的集合类NodeRecords.cs
using System;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
namespace drawtaskbytoolbar
{
public class NodeRecords
{
//保存所画节点的对象数组
public ArrayList nodeList=new ArrayList();
//空构造函数
public NodeRecords(){}
//添加节点
public bool AddNode(NodeClass node)
{
nodeList.Add(node);
return true;
}
//删除节点
public bool DeleteNode(NodeClass node)
{
for(int i=0;i<nodeList.Count;i++)
{
//节点名称唯一
if(((NodeClass)nodeList[i]).NodeName == node.NodeName)
{
nodeList.RemoveAt(i);
return true;
}
}
return false;
}
//公共属性(节点元素个数)
public int Count
{
get
{
return nodeList.Count;
}
}
//获取节点数组的第i个节点对象
public NodeClass GetNode(int i)
{
if(i>=0 & i<Count)
return (NodeClass)nodeList[i];
else
return null;
}
//根据节点名称获取节点
public NodeClass GetNode(string nodename)
{
for(int i=0;i<nodeList.Count;i++)
{
if(GetNode(i).NodeName == nodename)
return GetNode(i);
}
return null;
}
//判断节点数组中是否包含给定类型的节点
public bool HasNode(nodetypedefine nodetype)
{
for(int i=0;i<nodeList.Count;i++)
{
if(GetNode(i).NodeType == nodetype)
return true;
}
return false;
}
//新增加的节点命名为“任务k”,k始终不大于节点数,每删除或重命名一个,就产生一个
//可重复使用的节点名“任务j”,j<=节点总数,这样就可以把新增加的节点命名为“任务
//j”。这样可以始终保持节点名称的唯一。
//获取新增节点的默认名称
public string GetNewNodeName()
{
string nodename="";
int j=0;
for(int i=1;i<=nodeList.Count+1;i++)
{
nodename="任务"+i;
//在节点集合中找名称为任务i的节点
for(j=0;j<nodeList.Count;j++)
{
if(((NodeClass)nodeList[j]).NodeName == nodename)
break;
}
//如果找不到就退出外层循环,新增节点命名为任务i.否则继续循环.
if(j == nodeList.Count)
break;
}
//如果内外循环都被完整执行,则nodename为"任务"+(nodeList.Count+1)
return nodename;
}
//获取新的逻辑节点名称(保证逻辑节点名称的唯一性)
public string GetNewLogicNodeName(nodetypedefine nodetype)
{
string nodename="";
int j=0;
for(int i=1;i<=nodeList.Count+1;i++)
{
if(nodetype == nodetypedefine.andsplit)
nodename="And Split"+i;
if(nodetype == nodetypedefine.andjoin)
nodename="And Join"+i;
if(nodetype == nodetypedefine.orsplit)
nodename="Or Split"+i;
if(nodetype == nodetypedefine.orjoin)
nodename="Or Join"+i;
//在节点集合中找名称为任务i的节点
for(j=0;j<nodeList.Count;j++)
{
if(((NodeClass)nodeList[j]).NodeName == nodename)
break;
}
//如果找不到就退出外层循环,新增节点命名为任务i.否则继续循环.
if(j == nodeList.Count)
break;
}
//如果内外循环都被完整执行,则nodename为"任务"+(nodeList.Count+1)
return nodename;
}
//保存开始、结束及任务节点到数据库(使用带参数的sql命令是为了增加安全性)
public int SaveProcess(string processname,string tablename,string tablealias,
string identityfield,string
duedate)
{
string strSql"insert into ProcessDefinition(ProcessName,RelatedTable,
Alias,IdentifiedField,DueDate) values(@ProcessName,'"+tablename
+"','"+tablealias+"','"+identityfield+"',@DueDate)";
SqlCommand cmd;
try
{
cmd=new SqlCommand(strSql);
cmd.Parameters.Add("@ProcessName",SqlDbType.VarChar,50);
cmd.Parameters["@ProcessName"].Value=processname;
cmd.Parameters.Add("@DueDate",SqlDbType.SmallInt);
cmd.Parameters["@DueDate"].Value=int.Parse(duedate);
}
catch(System.FormatException ex)
{
MessageBox.Show("数据格式错误!");
return -1;
}
DataAccess database=new DataAccess();
if(! database.SQLExeNonQuery(cmd))
{
MessageBox.Show("保存流程失败!");
return -1;
}
//获取流程编号
strSql="select ProcessID from ProcessDefinition where ProcessName
= @ProcessName"
cmd=new SqlCommand(strSql);
cmd.Parameters.Add("@ProcessName",SqlDbType.VarChar,50);
cmd.Parameters["@ProcessName"].Value=processname;
DataSet ds=database.SQLExeDataSet(cmd);
string processID=ds.Tables[0].Rows[0]["ProcessID"].ToString();
//保存所有节点(包括节点名称、节点类型、任务节点包含的过程逻辑等)
string completeSql="";
for(int i=0;i<Count;i++)
{
//保存开始节点
if(GetNode(i).NodeType == nodetypedefine.start)
completeSql=completeSql+"insert into TaskDefinition
(ProcessID,TaskName,NodeType) values("+processID+",'"
+GetNode(i).NodeName+"','Start');";
//保存结束节点
if(GetNode(i).NodeType == nodetypedefine.end)
completeSql=completeSql+"insert into TaskDefinition
(ProcessID,TaskName,NodeType) values("+processID+",'"
+GetNode(i).NodeName+"','End');";
//保存任务节点
if(GetNode(i).NodeType == nodetypedefine.tasknode)
completeSql=completeSql+"insert into TaskDefinition
(ProcessID,TaskName,NodeType,ProcessLogic) values
("+processID+",'"+GetNode(i).NodeName+"','TaskNode','"
+GetNode(i).ProcessLogic+"');";
}
if(completeSql == "")
{
MessageBox.Show("没有可保存的节点!");
return -1;
}
//执行sql事务处理,保证节点保存操作的完整性
if(! database.ExeSQLNonQueryTransaction(completeSql))
{
MessageBox.Show("保存节点失败!"+database.BaseSqlErrDes);
return -1;
}
return int.Parse(processID);
}
}
}
相关文章推荐
- 第五章 工作流定义工具的设计与实现(七)
- 第五章 工作流定义工具的设计与实现(一)
- 第五章 工作流定义工具的设计与实现(二)
- 第五章 工作流定义工具的设计与实现(四)
- 第五章 工作流定义工具的设计与实现(五)
- 第五章 工作流定义工具的设计与实现(六)
- 第五章 工作流图形定义工具(八)-- 递归算法的使用
- 第五章 工作流图形定义工具(九)-- 递归算法的使用
- 办公自动化中工作流过程定义的设计与实现
- 基于WebServices简易网络聊天工具的设计与实现
- 在eclipse中设计BPMN 2.0工作流定义的根本步骤
- 模块管理常规功能自己定义系统的设计与实现(53--演示程序和视频解说 )
- 模块管理常规功能自己定义系统的设计与实现(22--第二个模块的增加)
- BPM, 业务流程图, 商业智能图,工作流自动化图,设计开发工具,可视化VC++控件源代码组件库
- 我的毕业设计论文:基于局域网的通信工具的设计与实现(一)
- 基于GMF的流程分析工具的设计与实现构思
- 开源->一步步实现cnblogs博客采集工具->概要设计
- 用Visio来做工作流定义工具
- 一个真正符合中国国情的工作流设计参考(包括PHP实现)
- 基于Extjs可视工作流设计器的实现