WF4.0自定义持久化

WF4提供了强大的持久化的功能,ms提供了SqlWorkflowInstanceStore 来进 行sqlserver的持久化,我研究了一下,DB里面有10个数据表,24个存储过程。 功能非常强大,但是也逻辑也比较复杂。这里我介绍自定义的持久化。持久化的 存储器也SqlServer。

1、设计数据表,表结构非常简单,如下图所示:

 

2、XmlWorkflowInstanceStore继承了InstanceStore:

代码

public class XmlWorkflowInstanceStore : InstanceStore
     {
       public  Guid ownerInstanceID;

         public XmlWorkflowInstanceStore() : this (Guid.NewGuid())
         {
         }
         public XmlWorkflowInstanceStore(Guid id)
         {
             ownerInstanceID = id;
         }
         //Synchronous version of the  Begin/EndTryCommand functions
         protected override bool TryCommand (InstancePersistenceContext context, InstancePersistenceCommand  command, TimeSpan timeout)
         {
             return EndTryCommand(BeginTryCommand (context, command, timeout, null, null));
         }
         //The persistence engine will send a variety  of commands to the configured InstanceStore,
         //such as CreateWorkflowOwnerCommand,  SaveWorkflowCommand, and LoadWorkflowCommand.
         //This method is where we will handle those  commands
         protected override IAsyncResult BeginTryCommand (InstancePersistenceContext context, InstancePersistenceCommand  command, TimeSpan timeout, AsyncCallback callback, object  state)
         {
             IDictionary<System.Xml.Linq.XName,  InstanceValue> data = null;
             //The CreateWorkflowOwner command  instructs the instance store to create a new instance owner  bound to the instanace handle
             if (command is  CreateWorkflowOwnerCommand)
             {
                 context.BindInstanceOwner (ownerInstanceID, Guid.NewGuid());
             }
             //The SaveWorkflow command instructs  the instance store to modify the instance bound to the  instance handle or an instance key
             else if (command is  SaveWorkflowCommand)
             {
                 SaveWorkflowCommand saveCommand =  (SaveWorkflowCommand)command;
                 data =  saveCommand.InstanceData;
                 Save(data);
             }
             //The LoadWorkflow command instructs  the instance store to lock and load the instance bound to  the identifier in the instance handle
             else if (command is  LoadWorkflowCommand)
             {
                 try
                 {
                         InstancesTable obj  = InstancesTableBiz.GetInstancesTable(this.ownerInstanceID);
                         System.Text.UTF8Encoding utf8 = new System.Text.UTF8Encoding ();
                         byte[] bs =  utf8.GetBytes(obj.InstanceXML);
                         System.IO.MemoryStream memoryStream = new System.IO.MemoryStream (bs);
                         data =  LoadInstanceDataFromFile(memoryStream);
                         context.LoadedInstance(InstanceState.Initialized, data, null, null,  null);
                 }
                 catch (Exception exception)
                 {
                     throw new  PersistenceException(exception.Message);
                 }
             }
             return new  CompletedAsyncResult<bool>(true, callback, state);
         }
         protected override bool EndTryCommand (IAsyncResult result)
         {
             return  CompletedAsyncResult<bool>.End(result);
         }
         //Reads data from xml file and creates a  dictionary based off of that.
         IDictionary<System.Xml.Linq.XName,  InstanceValue> LoadInstanceDataFromFile(Stream inputStream)
         {
             IDictionary<System.Xml.Linq.XName,  InstanceValue> data = new Dictionary<System.Xml.Linq.XName,  InstanceValue>();
             NetDataContractSerializer s = new  NetDataContractSerializer();
             XmlReader rdr = XmlReader.Create (inputStream);
             XmlDocument doc = new XmlDocument ();
             doc.Load(rdr);
             XmlNodeList instances =  doc.GetElementsByTagName("InstanceValue");
             foreach (XmlElement instanceElement in  instances)
             {
                 XmlElement keyElement =  (XmlElement)instanceElement.SelectSingleNode("descendant::key");
                 System.Xml.Linq.XName key =  (System.Xml.Linq.XName)DeserializeObject(s, keyElement);
                 XmlElement valueElement =  (XmlElement)instanceElement.SelectSingleNode("descendant::value");
                 object value =  DeserializeObject(s, valueElement);
                 InstanceValue instVal = new  InstanceValue(value);
                 data.Add(key, instVal);
             }
             return data;
         }
         object DeserializeObject(NetDataContractSerializer  serializer, XmlElement element)
         {
             object deserializedObject = null;
             MemoryStream stm = new MemoryStream ();
             XmlDictionaryWriter wtr =  XmlDictionaryWriter.CreateTextWriter(stm);
             element.WriteContentTo(wtr);
             wtr.Flush();
             stm.Position = 0;
             deserializedObject =  serializer.Deserialize(stm);
             return deserializedObject;
         }
         //Saves the persistance data to an xml  file.
         void Save(IDictionary<System.Xml.Linq.XName,  InstanceValue> instanceData)
         {
             //string fileName =  IOHelper.GetFileName(this.ownerInstanceID);
             XmlDocument doc = new XmlDocument ();
             doc.LoadXml ("<InstanceValues/>");

             foreach  (KeyValuePair<System.Xml.Linq.XName,InstanceValue> valPair in  instanceData)
             {
                 XmlElement newInstance =  doc.CreateElement("InstanceValue");
                 XmlElement newKey =  SerializeObject("key", valPair.Key, doc);
                 newInstance.AppendChild (newKey);
                 XmlElement newValue =  SerializeObject("value", valPair.Value.Value, doc);
                 newInstance.AppendChild (newValue);
                 doc.DocumentElement.AppendChild (newInstance);
             }
             //doc.Save(fileName);
             if (!string.IsNullOrEmpty (InstancesTableBiz.GetInstancesTable (this.ownerInstanceID).InstanceXML))
             {
                 InstancesTable obj =  InstancesTableBiz.GetInstancesTable(this.ownerInstanceID);
                 obj.InstanceXML =  doc.InnerXml;
                 InstancesTableBiz.UpdateInstancesTable(obj);
             }
             else
             {
                 InstancesTable obj = new  InstancesTable();
                 obj.id =  this.ownerInstanceID;
                 obj.InstanceXML =  doc.InnerXml;
                 InstancesTableBiz.AddInstancesTable(obj);
             }

        }
         XmlElement SerializeObject(string elementName,  object o, XmlDocument doc)
         {
             NetDataContractSerializer s = new  NetDataContractSerializer();
             XmlElement newElement =  doc.CreateElement(elementName);
             MemoryStream stm = new MemoryStream ();
             s.Serialize(stm, o);
             stm.Position = 0;
             StreamReader rdr = new StreamReader (stm);
             newElement.InnerXml = rdr.ReadToEnd ();
             return newElement;
         }
     }

时间: 2024-10-29 18:02:11

WF4.0自定义持久化的相关文章

WF4.0中实现子流程

工作流服务中,经常会在主流程启用一些子流程.我在审批流程中经常会使用bookmark来暂停流程,这篇文章,将结合bookmark来实现主流程启动子流程. 使用以前的一篇WF4.0自定义持久化中的自定义的持久化.不过数据表中加入了一个字段parentid,用于标识父流程: 下面用一个流程实例为例说明主流程是如何启用子流程,子流程又是如何返回主流程的,主流程如下:

WF4.0实战(二十三):自定义工作流活动的外观的两种方式

经常有童鞋在群里面问同样一个问题:如何自定义WF4.0活动的外观.其实一共有两种方式去实现自定义WF4.0活动的外观:一种方式我 在以前的博文上实现过,见:WF4.0实战(十一):邮件通知:另外一种方式我将在这里讲述它的实现.故这篇文章中,我将分别用这两种 方式去一个最简单的WF4.0自定义活动外观的例子. 第一种方式:使用[Designer]属性.命名空间为:using System.ComponentModel;代码如下: [Designer(typeof(CustomWriteLineDe

WF4.0中四种自定义类型活动

工作流中的活动就像用户自定义的控件,将许多的功能封装起来用.WF4.0中提供了四种可继承的活动 类:CodeActivity .AsyncCodeActivity.Activity.NativeActivity.这几种活动都有自己使用的适合 场合,正确的使用这些活动将非常有利. 1.CodeActivity WF4.0中的活动是树形结构的,创建叶子活动最简单是方式就是使用CodeActivity ,它的逻辑都放在 一个方法:Execute 里面,这个也是四种活动中最简单的一种.这里用一个简单的自

WF4.0实战(十四):ASP.NET结合WF4.0完整示例

有网友问如何在web中使用WF.今天我将实现一个完整的示例.这个示例将包括WF4.0的大部分知识点.包括: 1.持久化服务 2.跟踪服务 3.自定义扩展 4.WCF Workflow Service 5.WorkflowServiceHost 6.使用Interop活动去调用WF3.0工作流程 效果: 我先描述一下这个示例的功能,然后演示一下这个示例的功能,然后进一步的说明如何去实现. 这个示例是一个任务队列,这个示例在客户端有两个aspx页面.一个是用于用户输入请求的页面,这个请求会根据你选择

WF4.0实战

WF4.0实战(二十四) WF4定制个性化的WebService WF4.0实战(二十三):自定义工作流活动的外观的两种方式 WF4.0实战(二十二):一个实际生活中状态机的例子 WF4.0实战(二十一):Windows Server AppFabric中宿主WF4.0应用 WF4.0实战(二十):Windows Server AppFabric介绍 WF4.0实战(十九):Silverlight+WCF+WF+Linq结合的一个示例 WF4.0实战(十八):模拟asp.net生命周期 WF4.

WF4.0基础

WF4.0 基础篇(三十 完) 对学习WF的一点建议 WF4.0 基础篇(二十九) WorkflowInspectionServices WF4.0 基础篇(二十八) WF调用PowerShell WF4.0基础篇 (二十七) WCF Workflow Service 在WCF中使用WF WF4.0基础篇 (二十六) Interop调用WF3.X的Activity WF4.0基础篇 (二十五)(补充) ActivityFunc与InvokeFunc WF4.0 基础篇(二十五) Activity

WF4.0实战(二十一):Windows Server AppFabric中宿主WF4.0应用程序

在之前的一篇博文Windows Server AppFabric介绍上,简单的介绍了一下Windows Server AppFabric.这篇文章中,我将介绍一下,如 何在将WF4.0应用程序宿主到Windows Server AppFabric中,以及如何持久化配置和追踪配置. 首先,我将使用asp.net和WF4.0实现一个简单的Pizza订购系统.然后将这个应用系统宿主到Windows Server AppFabric上,实现持久化 ,跟踪等配置. Pizza订购系统: 分两部分,一个是a

【转】WF4.0实战系列索引

WF4.0实战系列索引       从WF4.0 betal1出来的时候就开始使用WF4.0,由于资料不多,学习过程也非常艰苦.今年四月份的时候打算写WF4.0实战系列,由于今年是本命年故坚持写了24篇文章.这个系列的文章都有一个特点,就是每篇文章都有一个实例,所以对初学者来说是很有帮助的.这个系列的绝大数文章和程序都是原创,少数是翻译和借鉴别人的.写一个文章索引,方便WF4的学习者查看.     WF4.0实战(一):文件审批流程     WF4.0实战(二):超市收银软件     WF4.0

WF4.0 流程设计器例子 (提供状态机模板)

WF4.0 的流程设计器,可根据流程启参数自动构建启动窗体, 根据Bookmark自动构建提交窗体,可保存,加载,调试VS2010设计的工作流文件,提供可视化的流程测试界面,可设计WF4.0的顺序工作流,FlowChar工作流,状态机工作流(注: WF4.0默认没有提供状态机,本例中的状态机是根据WF State Machine Activity Pack源代码修改实现的) 状态机模板 测试例子 打开测试流程 启动测试流程 跟踪,运行信息 本文示例源代码或素材下载