程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WF4.0自定義持久化

WF4.0自定義持久化

編輯:關於.NET

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;
         }
     }

3、設計書簽類:

代碼

public sealed class Read<TResult> :  NativeActivity<TResult>
     {
         public Read()
             : base()
         {
         }
         public string BookmarkName { get; set; }
         // Must return true for a NativeActivity  that creates a bookmark
         protected override bool CanInduceIdle
         {
             get { return true; }
         }
         protected override void Execute (NativeActivityContext context)
         {
             context.CreateBookmark(this.BookmarkName,  new BookmarkCallback(this.Continue));
         }
         void Continue(NativeActivityContext context,  Bookmark bookmark, object obj)
         {
             this.Result.Set(context, (TResult) obj);
         }
     }

4、設計三個書簽的流程:

5、自定定義持久化的使用

代碼

XmlWorkflowInstanceStore instanceStore = new  XmlWorkflowInstanceStore();
             WorkflowApplication application =  new WorkflowApplication(new Activity1());
             application.InstanceStore =  instanceStore;
             application.PersistableIdle = (e)  =>
             {
                 return  PersistableIdleAction.Unload;
             };
             application.Completed =  (workflowApplicationCompletedEventArgs) =>
             {
                 Console.WriteLine ("\nWorkflowApplication has Completed in the {0} state.",  workflowApplicationCompletedEventArgs.CompletionState);
             };
             application.Unloaded =  (workflowApplicationEventArgs) =>
             {
                 Console.WriteLine ("WorkflowApplication has Unloaded\n");
                 instanceUnloaded.Set();
             };
             instanceStore.ownerInstanceID =  application.Id;

             // continue executing this instance
             application.Run();
            //string a= application.GetBookmarks() [0].BookmarkName;
             instanceUnloaded.WaitOne();
             return application.Id; ;

6、Demo說明:

在Start.aspx,啟動一個流程

在Default.aspx,進行A,B,C三個站的審核。

總結:我現在做的項目使用了WF4.0,所有的審核流程都是使用這種書簽的機 制。但比這個Demo復雜很多。之所以要自定義持久化,還有一個原因是:ms的持 久化,當流程結束之後,實例的記錄就被自動刪除了。

出處:http://zhuqil.cnblogs.com

代碼: http://files.cnblogs.com/zhuqil/WorkflowConsoleApplication3.rar

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved