WWF提供的持续化功能会自动记录工作流实例以及它包含的所有活动的执行状态,这些状态并不是指工作流上流转的表单所呈现的业务逻辑状态。WWF持续化功能就是将未执行完成的工作流实例以及该实例中各种活动的状态,以文件或数据库方式进行存储,待需要的时候再重新将其加载回工作流运行时容器Runtime中。运行完毕才删除。

  在具体操作中通过"SqlWorkflowPersistenceService"类来实现持续化的功能,基于数据库,其他数据库需重新实现接口。

一、创建SqlPersistenceService数据库

  要在SQLServer实现工作流的保存、恢复功能,需要创建一些相关表与存储过程。默认情况下在C:\Windows\Microsoft.NET\Framework\v3.5\SQL\EN 路径下有SqlPersistenceProviderSchema.sql和SqlPersistenceProviderLogic.sql两个文件,打开SQLServer创建一个名叫SqlPersistenceService的数据库,按顺序执行以上两个sql脚本。此时,SqlPersistenceService数据库就创建了几个表与存储过程。

  如果实在不行,就把SqlPersistenceService数据库附加进来。http://files.cnblogs.com/kissdodog/WWF%E6%8C%81%E7%BB%AD%E5%8C%96%E6%95%B0%E6%8D%AE%E5%BA%93.rar

  接口如下:

   [ExternalDataExchange]  //using System.Workflow.Activities;
public interface IEvent
{
event EventHandler<ExternalDataEventArgs> PMApproved;
event EventHandler<ExternalDataEventArgs> VPApproved;
event EventHandler<ExternalDataEventArgs> StaffSubmit;
}

  新建一个工作流如下:

  

  里面是3个HandleExternalEvent活动,分别于刚刚定义的接口事件相绑定。

  

  在bin目录里面添加一个XML文件,其代码如下:

<WorkflowInstances />

  新建一个Winform程序,界面如下:

  

  代码如下:

    public partial class Form1 : Form, ClassLibrary1.IEvent
{
//创建一个WinForm引用程序,然后继承并实现接口中定义的事件
public event EventHandler<ExternalDataEventArgs> PMApproved;
public event EventHandler<ExternalDataEventArgs> VPApproved;
public event EventHandler<ExternalDataEventArgs> StaffSubmit; private WorkflowRuntime runtime;
//SQLServer中的"SqlPersistenceService"数据库是用来存储工作流实例及其活动的运行状态。
//业务逻辑状态也能够以XML文件形式进行存储,当程序刚运行无流程在运行时,添加一个空xml文件
//名为:workflowInstances.xml直接放在bin目录
const string instanceFilename = "workflowInstances.xml"; WorkflowInstance instance; public Form1()
{
InitializeComponent(); this.runtime = new WorkflowRuntime(); runtime.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs>(runtime_WorkflowCompleted);
runtime.WorkflowIdled += OnWorkflowIdled; //应用程序启动时以"SqlWorkflowPersistenceService"为对象来实例化"WorkflowPersistenceService"类,
//并通过"SqlWorkflowPersistenceService"来连接SQLServer数据库,同时将工作流的持续化服务加载到工作流运行时容器Runtime中。
WorkflowPersistenceService persistenceService =
new SqlWorkflowPersistenceService(
"server=CZZ;database=SqlPersistenceService;uid=sa;pwd=123");
runtime.AddService(persistenceService); ExternalDataExchangeService dataService = new ExternalDataExchangeService();
runtime.AddService(dataService); dataService.AddService(this); LoadWorkflowData(); runtime.StartRuntime(); }
//在工作流空闲状态时并将其从内存中卸载出去
//重载工作流的"WorkflowIdled"事件,当工作流处于等待状态下时将通过该事件来调用工作流实例的"TryUnload()"方法,
//使它激发工作流的"WorkflowPersisted"事件,这样工作流就可以通过"WorkflowPersistenceService"服务将信息自动保存到SQL Server数据库,以实现持续化功能。
static void OnWorkflowIdled(object sender, WorkflowEventArgs e)
{
e.WorkflowInstance.TryUnload();
} //当工作流完成后,将界面列表中的相应数据删除
//当工作流运行结束时还需要对界面列表中的相关信息进行删除,用户可以通过重载工作流的"WorkflowCompleted"事件来实现。
//要注意分清楚,事件是工作流的事件,而删除界面是WinForm程序的事。工作流与应用程序不在同一个线程,因此不能直接调用。这种情况可以通过委托来实现。
void runtime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)
{
RemoveListViewItem remove = new RemoveListViewItem(RemoveListViewItemAsync);
Invoke(remove, e.WorkflowInstance.InstanceId);
}
private delegate void RemoveListViewItem(Guid instanceId);
private void RemoveListViewItemAsync(Guid instanceId)
{
foreach (ListViewItem item in ListViewExisting.Items)
{
if (item.SubItems[].Text.Equals(instanceId.ToString()))
ListViewExisting.Items.Remove(item);
}
} //用户提交请假单的按钮事件
private void btnSubmit_Click(object sender, EventArgs e)
{
instance = runtime.CreateWorkflow(typeof(WorkflowConsoleApplication1.Workflow1));
instance.Start(); StaffSubmit(null, new ExternalDataEventArgs(instance.InstanceId)); ListViewExisting.Items.Add(new ListViewItem(new String[] { instance.InstanceId.ToString(), this.txtDay.Text, "提交请假单" })); }
//当窗体关闭时,将列表中请假单的信息保存到XML中
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
SaveWorkflowData();
runtime.Dispose();
}
//项目经理审批的按钮
private void btnPMArrpoved_Click(object sender, EventArgs e)
{
instance = runtime.GetWorkflow(new Guid(ListViewExisting.SelectedItems[].Text)); PMApproved(null, new ExternalDataEventArgs(instance.InstanceId)); foreach (ListViewItem item in ListViewExisting.Items)
{
if (item.SubItems[].Text.Equals(instance.InstanceId.ToString()))
item.SubItems[].Text = "等待VP审批";
}
}
//副总经理审批的按钮
private void btnVPApproved_Click(object sender, EventArgs e)
{
instance = runtime.GetWorkflow(new Guid(ListViewExisting.SelectedItems[].Text));
VPApproved(null, new ExternalDataEventArgs(instance.InstanceId));
foreach (ListViewItem item in ListViewExisting.Items)
{
if (item.SubItems[].Text.Equals(instance.InstanceId.ToString()))
item.SubItems[].Text = "审批通过";
}
}
#region 读写XML的方法
/// <summary>
/// 从XML文件中读取已经钝化的工作流实例的信息
/// </summary>
public void LoadWorkflowData()
{
XmlTextReader reader = new XmlTextReader(instanceFilename);
try
{
while (reader.Read())
{
if (reader.Name.Equals("WorkflowInstance"))
{
ListViewExisting.Items.Add(
new ListViewItem(
new String[] { reader.GetAttribute("InstanceId"),
reader.GetAttribute("Day"),
reader.GetAttribute("State")}));
}
}
reader.Close();
}
catch (FileNotFoundException) { }
}
/// <summary>
/// 保存工作流实例的信息到XML文件中
/// </summary>
public void SaveWorkflowData()
{
XmlTextWriter writer = new XmlTextWriter(instanceFilename, Encoding.Unicode);
writer.WriteStartElement("WorkflowInstances");
foreach (ListViewItem item in ListViewExisting.Items)
{
writer.WriteStartElement("WorkflowInstance");
writer.WriteAttributeString("InstanceId", item.SubItems[].Text);
writer.WriteAttributeString("Day", item.SubItems[].Text);
writer.WriteAttributeString("State", item.SubItems[].Text);
writer.WriteEndElement();
}
writer.WriteEndElement();
writer.Flush();
writer.Close();
}
#endregion
}

  执行效果如下:

  

  由于在关闭窗口的时候,会将当前工作流的执行状态保存到XML文件和数据库中,而下次打开的时候,回去读取上次执行到的状态,所以当工作流执行到某一步关闭窗口再打开,会显示上次保存的状态。

WWF3的持续化<第五篇>的更多相关文章

  1. 【Python五篇慢慢弹(4)】模块异常谈python

    模块异常谈python 作者:白宁超 2016年10月10日12:08:31 摘要:继<快速上手学python>一文之后,笔者又将python官方文档认真学习下.官方给出的pythondo ...

  2. 前端工程师技能之photoshop巧用系列第五篇——雪碧图

    × 目录 [1]定义 [2]应用场景 [3]合并[4]实现[5]维护 前面的话 前面已经介绍过,描述性图片最终要合并为雪碧图.本文是photoshop巧用系列第五篇——雪碧图 定义 css雪碧图(sp ...

  3. WWF3追踪功能<WWF第六篇>

    WWF工作流提供了Tracking跟踪功能来对工作流实例及其所包含的活动在运行时的状态进行跟踪,以便用户在需要时可以通过这些历史信息进行分析.WWF的Tracking跟踪功能是通过"SqlT ...

  4. ElasticSearch入门 第五篇:使用C#查询文档

    这是ElasticSearch 2.4 版本系列的第五篇: ElasticSearch入门 第一篇:Windows下安装ElasticSearch ElasticSearch入门 第二篇:集群配置 E ...

  5. 持续化集成Jenkins的系统配置

    最近在研究selenium2自动化测试,用到持续化集成jenkins.由于之前仅限于使用,而没有真正动手配置过,所以现在学习从零开始,搭建持续化集成,故而有了这篇博客. 先介绍一下项目持续集成测试,这 ...

  6. mysql第五篇 : MySQL 之 视图、触发器、存储过程、函数、事物与数据库锁

    第五篇 : MySQL 之 视图.触发器.存储过程.函数.事物与数据库锁 一.视图 视图是一个虚拟表(非真实存在的),其本质是‘根据SQL语句获取动态的数据集,并为其命名‘ ,用户使用时只需使用“名称 ...

  7. 【Python五篇慢慢弹】快速上手学python

    快速上手学python 作者:白宁超 2016年10月4日19:59:39 摘要:python语言俨然不算新技术,七八年前甚至更早已有很多人研习,只是没有现在流行罢了.之所以当下如此盛行,我想肯定是多 ...

  8. 【Python五篇慢慢弹】数据结构看python

    数据结构看python 作者:白宁超 2016年10月9日14:04:47 摘要:继<快速上手学python>一文之后,笔者又将python官方文档认真学习下.官方给出的pythondoc ...

  9. 【Python五篇慢慢弹(3)】函数修行知python

    函数修行知python 作者:白宁超 2016年10月9日21:51:52 摘要:继<快速上手学python>一文之后,笔者又将python官方文档认真学习下.官方给出的pythondoc ...

随机推荐

  1. 推荐一个css帮助手册的版本 同时提供chm和在线

    版本保持更新 目录分类妥当 查阅很方便 就是习惯了jquery那种风格,略有不适应. 包括最新css3的内容 网址: http://css.doyoe.com/ chm下载地址: http://css ...

  2. 使ViewStub 来提高UI的加载的性能

    首先看下API中的ViewStub 根据的文档的说明,ViewStub是一种默认不可见的试图,它没有大小,所以不能被改变,也不能通过某些把viewstub添加到布局当中来, 不过我们可以使用infla ...

  3. 图片_ _图片缓存之内存缓存技术LruCache,软引用

    每当碰到一些大图片的时候,我们如果不对图片进行处理就会报OOM异常,这个问题曾经让我觉得很烦恼,后来终于得到了解决,那么现在就让我和大家一起分享一下吧.这篇博文要讲的图片缓存机制,我接触到的有两钟,一 ...

  4. JQ获取当前是第几个元素,以及直接选取第几个元素的方法

    一.获取当前是第几个元素的方法使用:$(this).index() 实例: $(function () { $('.menu li').mouseover(function () { alert($( ...

  5. Laravel 部署安装到虚拟主机的方法(折腾了一周,终于成功部署,原来是虚拟机不加载.env,谢谢莫回首http://lxl520.com/index.php/archives/88/!)

      作者:莫回首链接:https://www.zhihu.com/question/35497879/answer/111241182来源:知乎著作权归作者所有,转载请联系作者获得授权. 序 lara ...

  6. js实现的新闻列表垂直滚动实现详解

    js实现的新闻列表垂直滚动实现详解:新闻列表垂直滚动效果在大量的网站都有应用,有点自然是不言而喻的,首先由于网页的空间有限,使用滚动代码可以使用最小的空间提供更多的信息量,还有让网页有了动态的效果,更 ...

  7. 播放wav聲音格式

    1. #import <AudioToolbox/AudioToolbox.h> 2.聲明 成員变量 SystemSoundID soundID; 3.播放 - (void)playSou ...

  8. samba共享修改匿名用户为非nobody

    samba共享修改匿名用户为非nobody 1)linux的samba用户,如果开启匿名用户登陆共享权限,security 设置为 share ,配置如下:[root@centos69:~]$grep ...

  9. 94、EventBus框架 ---- 转载

    EventBus使用之基础 http://blog.csdn.net/yanbober/article/details/45667363 EventBus框架库代码走读  http://blog.cs ...

  10. .NET Session操作

    public class SessionHelper { /// <summary> /// 根据session名获取session对象 /// </summary> /// ...