随笔 - 234, 文章 - 12, 评论 - 1671, 阅读 - 74万
  博客园  :: 首页  :: 联系 :: 订阅 订阅  :: 管理

WF4持久化:SqlWorkflowInstanceStore

Posted on   生鱼片  阅读(4691)  评论(9编辑  收藏  举报

WF4提供了强大的持久化模型,之前我也翻译了一篇文章描述了WF4中持久化的一些知识,[译]Windows Workflow Foundation 4 和持久性

我会系统的介绍下WF4中的持久化服务。WF4提供了一个抽象类InstanceStrore,表示逻辑上的工作流实例的容器,还有一些和持久化相关的类如LoadWorkflowCommandSaveWorkflowCommand等,具体的实现我们可以从InstanceStore类继承来开发自己的Persistence ProviderWF4已经默认给我们实现好了一个基于SQL的持久化实现,对应于SqlWorkflowInstanceStore类。下面是这两个类的继承关系:

clip_image002

下面是关于SqlWorkflowInstanceStore类属性的一些说明:

Instance Encoding Option:指定保存到持久化存储的压缩算法,可选值为GZipNone

Instance Completion Action:指定当工作流实例完成后的操作(是否删除持久化存储中的数据),有两个值DeleteAll(默认),DeleteNothing

Instance Locked Exception Action:当发生InstanceLockedException时发生的操作,该异常发生在当他要去锁定已经被其他服务宿主锁定的实例时。有几个值NoRetryBasicRetryAggressiveRetry

Host Lock Renewal Period:服务宿主在指定时间内必须更新锁定时间周期。 

下面就简单说明下如何使用SqlWorkflowInstanceStore来完成工作流的持久化操作,在开始这个例子前需要先建立持久化数据库。

1.       定义一个ReadLine自定义活动,如下:

public sealed class ReadLine : NativeActivity<string>

    {

        public ReadLine()

        {

        }

 

        public InArgument<string> BookmarkName { get; set; } 

        protected override bool CanInduceIdle

        {

            get

            {

                return true;

            }

        }

 

        protected override void Execute(NativeActivityContext context)

        {

            string name = this.BookmarkName.Get(context);

            if (name == null)

            {

                throw new ArgumentException(string.Format("ReadLine {0}: BookmarkName cannot be null", this.DisplayName), "BookmarkName");

            }

            context.CreateBookmark(name, new BookmarkCallback(OnReadComplete));

        }

 

        void OnReadComplete(NativeActivityContext context, Bookmark bookmark, object state)

        {

            string input = state as string;

 

            if (input == null)

            {

                throw new ArgumentException(string.Format("ReadLine {0}: ReadLine must be resumed with a non-null string"), "state");

            }

            context.SetValue(base.Result, input);

        }

    }

}

 

2.工作流中我们使用ReadLine等待输入,设计如下:

clip_image004

3.       宿主程序如下:

namespace CaryPersisten

{

    class Program

    {

        static InstanceStore instanceStore;

        static AutoResetEvent instanceUnloaded = new AutoResetEvent(false);      

        static Guid id;       

 

        static void Main(string[] args)

        {

            instanceStore =new SqlWorkflowInstanceStore("server=.;database=SampleInstanceStore;uid=sa;pwd=123456");

            InstanceView view = instanceStore.Execute(instanceStore.CreateInstanceHandle(), new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(30));

            instanceStore.DefaultInstanceOwner = view.InstanceOwner;

 

            WorkflowApplication application = new WorkflowApplication(new Workflow1());

            application.InstanceStore = instanceStore;           

            application.PersistableIdle = (e) =>

            {

                return PersistableIdleAction.Unload;

            };

            application.Unloaded = (e) =>

            {

                instanceUnloaded.Set();

            };

            application.Persist();

            id = application.Id;

            application.Run();

            instanceUnloaded.WaitOne();

 

            string input = Console.ReadLine();

            WorkflowApplication application1 = new WorkflowApplication(new Workflow1());

            application1.InstanceStore = instanceStore;

            application1.Completed = (workflowApplicationCompletedEventArgs) =>

            {

                Console.WriteLine("\nWorkflowApplication has Completed in the {0} state.", workflowApplicationCompletedEventArgs.CompletionState);

            };

            application1.Unloaded = (workflowApplicationEventArgs) =>

            {

                Console.WriteLine("WorkflowApplication has Unloaded\n");

                instanceUnloaded.Set();

            };

            application1.Load(id);

            application1.ResumeBookmark("nabookmark", input);

            instanceUnloaded.WaitOne();           

            Console.ReadLine();

        }

    }

}

 

4.在宿主程序中首先我们创建SqlWorkflowInstanceStore的实例,并将WorkflowApplicaiton的InstanceStore属性设置为该实例来指定使用的持久化存储。我们在自定义活动创建了书签,创建书签会让工作流变为idle状态进行持久化操作,工作流持久化后我们可以看到数据库的信息如下:

clip_image006

接收到输入后恢复书签,并将持久化数据库中的工作流实例装载到内存中继续运行工作流。

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
历史上的今天:
2008-12-09 MOSS程序中如何发Mail?
点击右上角即可分享
微信分享提示