WF4.0自定义持久化

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

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

  

2、自定义的SqlServerWorkflowInstanceStore继承了InstanceStore:

代码
 public class SqlServerWorkflowInstanceStore : InstanceStore
    {
      
public  Guid ownerInstanceID;
        
        
public SqlServerWorkflowInstanceStore() : this(Guid.NewGuid())
        {

        }

        
public SqlServerWorkflowInstanceStore(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, nullnull));
        }

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

            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, 
nullnullnull);
                }
                
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);
        }

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

        void Save(IDictionary<System.Xml.Linq.XName, InstanceValue> instanceData)
        {

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

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

        
// 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、自定义持久化的使用

代码
  SqlServerWorkflowInstanceStore  instanceStore = new  SqlServerWorkflowInstanceStore ();

            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三个站的审核。

备注:运行环境是VS2010 BETA2。

代码:/Files/zhuqil/WorkflowConsoleApplication3.rar

 



(全文完)


以下为广告部分

您部署的HTTPS网站安全吗?

如果您想看下您的网站HTTPS部署的是否安全,花1分钟时间来 myssl.com 检测以下吧。让您的HTTPS网站变得更安全!

SSL检测评估

快速了解HTTPS网站安全情况。

安全评级(A+、A、A-...)、行业合规检测、证书信息查看、证书链信息以及补完、服务器套件信息、证书兼容性检测等。

SSL证书工具

安装部署SSL证书变得更方便。

SSL证书内容查看、SSL证书格式转换、CSR在线生成、SSL私钥加解密、CAA检测等。

SSL漏洞检测

让服务器远离SSL证书漏洞侵扰

TLS ROBOT漏洞检测、心血漏洞检测、FREAK Attack漏洞检测、SSL Poodle漏洞检测、CCS注入漏洞检测。

posted @ 2010-01-12 10:59  麒麟  阅读(6678)  评论(22编辑  收藏  举报