WF基础+持久化实例总结

从面向对象到面向服务,接触到的理念越来越多,视野也在逐渐扩大,对面向对象这种理念的感觉似乎也在一天天发生着很多不同的变化。很多原来没想过的,现在大家都在开始去讨论它们具体的实现了,看来真是学无止境啊!

一、SOA理念

接触到SOA这个理念其实已经有一段时间了,面向服务,针对于编程中的组件,模块或者说功能单元,为它们提供接口和服务。是对面向对象思想的一种补充。我们用到的WCF也是基于此思想实现的。

而工作流(Workflow),指“业务过程的部分或整体在计算机应用环境下的自动化。工作流主要解决的主要问题是:为了实现某个业务目标,利用计算机在多个参与者之间按某种预定规则自动传递文档、信息或者任务。

其实这里看到的吸引人的还是‘自动化’这个词,从这里看出,应用工作流,我们可以让我们开发出来的软件根据需求自动实现自己的功能,最大程度上脱离人工操作或后台代码的编写。

二、WF基础

1、三种类型:顺序,流程图和状态机。

其中状态机工作流是开发中最常用的也是功能最强大的一种。

2、启动工作流的两种方式:

1、通过invoke的方式,在启动的主线程中启动相应的工作流

Activity activity = newDocActivity ();

WorkflowInvoker.Invoke(activity);

2、微软提供的一种application操作

3、书签

在工作流中,通过书签来使工作流能够停下来去接收一些参数或具体的操作等。

4、WF持久化

如何能更好的实现自动化,在用户审批或者中间进行其他相应操作时,能不限定时间,或者更加方便,这就用到了WF持久化。

WF持久化SQL: .NET Framework 4.5安装程序将与 SQL
工作流实例存储功能相关联的 SQL脚本文件复制到
%WINDIR%\Microsoft.NET\Framework\v4.xxx\SQL\EN文件夹。 SQL
工作流实例存储用于持久保存工作流实例的 SQL Server 2005或SQL Server 2008
数据库,运行这些脚本文件。 首先运行 SqlWorkflowInstanceStoreSchema.sql文件,然后运行 SqlWorkflowInstanceStoreLogic.sql文件。

通过以上操作就可以建立好WF持久化SQL的数据库了。利用持久化技术,用户审批工作的时候,就可以随时根据自己的安排来进行了。持久化数据库会将系统的当前状态完全重现在用户面前。

三、WF实例应用

最常见的应用工作流的例子:请假审批。当一个申请者提交申请后,工作流会自动将申请提交给指定的审批人,进行具体的审批操作,然后在决定是否继续流转。下面这段代码会将上面涉及到所有关上面说到的WF的基础

总体流程设计如下图:

从start开始进入工作流开始到状态1为止,整个小demo中声明了一个num的变量,T1:条件1如果Num大于5,那么直接进入结束状态,T2:条件2如果Num小于5,那么返回状态1,重新审批。

里面用到的是一个顺序流,InputName为参数。wait4InputActivity为创建的一个代码活动,具体实现如下;

 public sealed class wait4InputActivity : NativeActivity //NativeActivity允许创建书签
    {
        // 定义一个字符串类型的活动输入参数
        public InArgument<string> BookMarkName { get; set; }
        public OutArgument<int> Num { get; set; }

        protected override bool CanInduceIdle
        {
            get
            {
                return true ;
            }
        }

        // 如果活动返回值,则从 CodeActivity<TResult>
        // 派生并从 Execute 方法返回该值。
        protected override void Execute(NativeActivityContext context)
        {
            // 获取 Text 输入参数的运行时值
            //string text = context.GetValue(this.Text);
            string name = context.GetValue(BookMarkName);
           //创建书签,这时,工作流会空闲下来,这时会进行持久化工作
            context.CreateBookmark(name,new BookmarkCallback (ContinueExcuteWorkFlow));

        }
        //object:value值,是当我们让工作流继续往下执行的时候,传来的参数
        private void ContinueExcuteWorkFlow(NativeActivityContext context, Bookmark bookmark, object value)
        {
            //当我们调用了工作流一个方法让工作流继续往下执行的时候,首先执行此方法
            context.SetValue(Num,(int)value);
        }
    }

那么启动工作流,然后执行,在此之前,将工作流涉及到的公共的部分的代码抽出来,作为一个静态类如下:

 public static  class WorkflowApplicationHelper
    {
//通过配置文件链接WF持久化数据库
       public static string WorkFlowSqlconn;
       static WorkflowApplicationHelper()       {
           WorkFlowSqlconn = ConfigurationManager.AppSettings["SqlWorkflowInstanceStore"];
       }

       //创建工作流实例,并且执行之
       public static WorkflowApplication CreateHttpApplicationAndRun(Activity activity,IDictionary <string,object> inputs) {
//利用application来控制工作流
           WorkflowApplication application = new WorkflowApplication(activity,inputs);
           //创建工作流序列化需要的SQL序列化对象

           SqlWorkflowInstanceStore store = new SqlWorkflowInstanceStore(WorkFlowSqlconn);
           //使得当前application对象的实例关联期创建的实例
           application.InstanceStore = store;

           application.OnUnhandledException += m =>
           {
               Console.WriteLine("工作流出现了未处理的异常");
               return UnhandledExceptionAction.Terminate;
           };
           application.Unloaded += m =>
           {
               Console.WriteLine("工作流卸载!");
           };
           application.PersistableIdle += a =>
           {
               Console.WriteLine("工作流进行序列化!");
               return PersistableIdleAction.Unload;
           };
           application.Aborted += ea =>
           {
               Console.WriteLine("工作流崩了!");
           };
           application.Idle += m => {
               Console.WriteLine("工作流空闲下来了");
           };

           application.Run();
           return application ;
       }

       public static WorkflowApplication  LoadWorkFlowApplication(Activity activity,Guid id)
       {
           WorkflowApplication application = new WorkflowApplication(
               activity);  //这里不需要再传参数了
           //创建工作流序列化需要的SQL序列化对象
           SqlWorkflowInstanceStore store = new SqlWorkflowInstanceStore(WorkFlowSqlconn);
           //使得当前application对象的实例关联期创建的实例
           application.InstanceStore = store;

           application.OnUnhandledException += m =>
           {
               Console.WriteLine("工作流出现了未处理的异常");
               return UnhandledExceptionAction.Terminate;
           };
           application.Unloaded += m =>
           {
               Console.WriteLine("工作流卸载!");
           };
           application.PersistableIdle += a =>
           {
               Console.WriteLine("工作流进行序列化!");
               return PersistableIdleAction.Unload;
           };
           application.Aborted += ea =>
           {
               Console.WriteLine("工作流强制退出了!");
           };
           application.Idle += m =>
           {
               Console.WriteLine("工作流空闲下来了");
           };

           //从数据库中加载application状态
           application.Load(id);
           return application;
       }
}

那么在启动工作流时,只需要:

var inputs= new Dictionary<string, object>() {
                  {"InputName",DateTime .Now .ToString ()},
                  { "TempBookMarkName",this.txtBookMark .Text }};

             WorkflowApplication  application =WorkflowApplicationHelper .CreateHttpApplicationAndRun (new DocActivity (),inputs);
           txtID .Text=application .Id .ToString ();//记录application的id

此时,在调用helper时,会将工作流实例的当前状态存储到持久化数据库中去。如果我们关闭程序,在打开时,点击恢复书签时,将保存的id赋给application对象,还会执行原来被保存的实例。

恢复书签:

<span style="white-space:pre">	</span>WorkflowApplication application=WorkflowApplicationHelper.LoadWorkFlowApplication(new DocActivity (),Guid.Parse (txtID .Text ));
            application.ResumeBookmark(this.txtBookMark.Text, int.Parse(txtNum.Text));

经过以上步骤,工作流持久化就完成了。根据这个原理,我们可以利用工作流持久化来完成很多诸如审批这样跨越时间的实际性的工作。确实是很强大的一种思想。

那么以上也只是关于WF的一个小小的实例,如何把WF真正应用到开发中,还需要不断的研究,比如WF如何与泛型结合才能最大程度的抽象,WF内部有很多方法利用委托来实现,那么在业务上如何与委托去结合使用才能更大程度的发挥它强大的面向服务的力量呢,还是值得我们去再进一步讨论的。

时间: 2024-11-20 00:27:51

WF基础+持久化实例总结的相关文章

SQL 查询基础(2)-实例

上次说到SQL查询语句的逻辑执行过程,现在来用一个实例说明一下逻辑执行的过程. 前提:我们有三个表,分别记住客户信息.订单信息和产品信息 客户信息表:Customer ID,Name,Adress,PhoneNumber ID Name Adress PhoneNumber 1 CompanyA No.1 Street 123456 2 CompanyB No.2 Street 23453 3 CompanyC No.3 Street 45321 4 CompanyD No.4 Street 4

C#基础与实例教程最简单的C#快速入门教程【转自:http://www.82011433.com/Html/?6982.html】

c#基础与实例教程最简单的C#快速入门教程 在一小时内学会C#.使用例程,简单却完整的探索C#语言的构造和特点.本文特别适合有C++基础却没有太多精力学习C#的读者. 简介 C#是一种具有C++特性,Java样式及BASIC快速建模特性的编程语言.如果你已经知晓C++语言,本文将在不到一小时的时间内带你快速浏览C#的语法.如果熟悉Java语言,Java的编程结构.打包和垃圾回收的概念肯定对你快速学习C#大有帮助.所以我在讨论C#语言构造的时候会假设你知道C++. c#基础与实例教程最简单的C#快

AutoCAD ObjectARX(VC)开发基础与实例教程2014版光盘镜像

AutoCAD ObjectARX(VC)开发基础与实例教程2014,最新版,光盘镜像 作者:张帆 朱文俊 编著 出版社:中国电力出版社 出版时间:2014年6月 点击一下

Java 找出四位数的全部吸血鬼数字 基础代码实例

/** * 找出四位数的全部吸血鬼数字 * 吸血鬼数字是指位数为偶数的数字,能够由一对数字相乘而得到,而这对数字各包括乘积的一半位数的数字,当中从最初的数字中选取的数字能够随意排序. * 以两个0结尾的数字是不同意的. *   比例如以下列数字都是吸血鬼数字 1260=21*60 1827=21*87 2187=27*81 ... * 比較笨的低效率的做法: 遍历全部四位数, 每生成一个四位数的时候, *         在双重循环遍历两位数,在两位数的内层循环中推断是否与最外层循环的四位数相等

WinForm之BindingSource基础操作实例教程

通常我们在进行数据绑定的时候,常用的数据源有DataSet.DataTable.BindingList<T>.还有强类型数据源.今天我们来通过实例了解一下BindingSource组建,分享给大家供大家参考借鉴之用. BindingSource的两个用途: (1)首先,它提供一个将窗体上的控件绑定到数据的间接层.这是通过将 BindingSource 组件绑定到数据源,然后将窗体上的控件绑定到 BindingSource 组件来完成的.与数据的所有进一步交互(包括导航.排序.筛选和更新)都是通

C#反射之基础应用实例总结

本文将反射的东西整理了一下 , 提供了最全面的东西 , 当然也是基础的东西 , 在学好了这一切的基础上 , 大家可以学习反射的具体插件等应用 首先我们建立一个类库 , 将它生成为 reflectPrj .dll, 代码如下: using System; using System.Collections.Generic; using System.Text; namespace reflectPrj { /// <summary> /// 接口 /// </summary> publ

C#验证码识别基础方法实例分析

本文实例讲述了C#验证码识别基础方法,是非常实用的技巧.分享给大家供大家参考.具体方法分析如下: 背景 最近有朋友在搞一个东西,已经做的挺不错了,最后想再完美一点,于是乎就提议把这种验证码给K.O.了,于是乎就K.O.了这个验证码.达到单个图片识别时间小于200ms,500个样本人工统计正确率为95%.由于本人没有相关经验,是摸着石头过河.本着经验分享的精神,分享一下整个分析的思路.在各位大神面前献丑了. 再来看看部分识别结果如下图所示: 这里是不是看着很眼熟?下面再来具体分析一下. 处理第一步

Vue.js 基础指令实例讲解(各种数据绑定、表单渲染大总结)——新手入门、高手进阶

Vue.js 是一套构建用户界面的渐进式框架.他自身不是一个全能框架--只聚焦于视图层.因此它非常容易学习,非常容易与其它库或已有项目整合.在与相关工具和支持库一起使用时,Vue.js 也能完美地驱动复杂的单页应用.他是基于AnjularJs 编写的,所以和前者的语法特别相似,却又使用简洁了很多. 那今天,我就给大家详细的说道说道这个 Vue.js ,以下是我们这次详解的目录,朋友们可以根据自己的情况选择性阅读,所有操作均附有代码实现. 1. Vue.js 如何绑定到页面中,使用他的功能. 2.

java基础学习05(面向对象基础01--类实例分析)

面向对象基础01(类实例分析) 实现的目标 1.如何分析一个类(类的基本分析思路) 分析的思路 1.根据要求写出类所包含的属性2.所有的属性都必须进行封装(private)3.封装之后的属性通过setter和getter设置和取得4.如果需要可以加入若干构造方法 5.再根据其它要求添加相应的方法6.类中的所有方法都不要直接输出,而是交给被调用处调用 Demo 定义并测试一个名为Student的类,包括属性有"学号"."姓名"以及3门课程"数学".