Workflow Foundation 4.0 - PersistenceParticipant

Ambily.raj
Posted by in WWF category on for Advance level | Points: 250 | Views : 16191 red flag
Rating: 5 out of 5  
 1 vote(s)

We already discussed about Persistence and Extensions in workflow foundation 4.0. Persistence is the way of storing the current state of a workflow into an instance store. Extensions are special classes for sharing data among child activities, workflow and Host application. In case of normal Extension, the data shared using the Extension won’t be stored to the instance store as part of the Persistence.

Introduction

We already discussed about Persistence and Extensions in workflow foundation 4.0. Persistence is the way of storing the current state of a workflow into an instance store. Extensions are special classes for sharing data among child activities, workflow and Host application. In case of normal Extension, the data shared using the Extension won’t be stored to the instance store as part of the Persistence.


In real business scenario, we may need to store the Extension data as part of the workflow state. For this purpose, workflow foundation 4.0 is providing a special kind of Extension. In this article we will discuss about this special extension and how we can use the same.

PersistenceParticipant Extension

This special extension is a class which inherited from the System.Activities.Persistence.PersistenceParticipant base class.  For implementing the PersistenceParticipant, we need to override two methods CollectValues and PublishValues.
 
Here, for our sample we have small Persistence Participant extension which stores a collection of strings in an Items list.  Same way we have a normal extension class to store the data in an Items list.

Normal Extension

For more details on Extension, please refer Workflow Foundation 4.0 - Extension 
  

public class NormalExtension

    {

        private List<object> items = new List<object>();

 

        public List<object> Items

        {

            get

            {

                if (items == null)

                {

                    items = new List<object>();

                }

                return items;

            }

        }

    }


PersistenceParticipant Extension

As the Items list is a read write property, in CollectValues method, we need to assign the Item value to readWriteValues and assign null to writeOnlyValues. In PublishValues method, extract the Items value from readwriteValues dictionary and assign to Items property.

 

public class MyPersistenceParticipant:PersistenceParticipant

    {

        static XNamespace myNamespace = XNamespace.Get("MyApp");

        static XName currentItems = myNamespace.GetName("Items");

 

        private List<object> items = new List<object>();

 

        public List<object> Items

        {

            get

            {

                if (items == null)

                {

                    items = new List<object>();

                }

                return items;

            }

        }

 

        protected override void CollectValues(out IDictionary<XName, object> readWriteValues, out IDictionary<XName, object> writeOnlyValues)

        {

            readWriteValues = new Dictionary<XName, object>(1) { { currentItems, this.items } };

            writeOnlyValues = null;

        }

 

        protected override void PublishValues(IDictionary<XName, object> readWriteValues)

        {

            object loadedData;

            if (readWriteValues.TryGetValue(currentItems, out loadedData))

            {

                items = (List<object>)loadedData;

            }

        }

       

    }

Workflow

For understanding the difference between the normal extension and Persistence participant, we have a small workflow.


Here Close_Bookmark is a custom activity to create bookmark with name “Close”. For more details on Bookmark, please refer Workflow Foundation 4.0 – Bookmark.

Host application

For verifying our Persistence Participant extension, we will use the following Host application code.

Create an Instance of the workflow application and set the Instance Store. After that, add the objects of Normal as well as PersistenceParticipant extensions with one Item added to the Items property to the Extension collection of our workflow application.  

For our sample, we need to unload the instance completely from memory, so called the Unload method instead of Persist method. This will store the workflow state to instance store and remove the workflow application object from memory.

Now, for reloading the workflow from instance store, create the workflow application object, setup instance store and add extension objects to the workflow application object. After reloading, loop through the Items collection of both normal extension and PersistenceParticipant extension and display the items.

static void Main(string[] args)

        {           

            WorkflowApplication wfApp = new WorkflowApplication(new Workflow1());

            InstanceStore store = new SqlWorkflowInstanceStore(@"Data Source=.;Initial Catalog=SqlWorkflowInstanceStore;Integrated Security=True");

            wfApp.InstanceStore = store;

 

            NormalExtension normalObj = new NormalExtension();

            normalObj.Items.Add("Normal Extension: Before Persist");

 

            MyPersistenceParticipant obj = new MyPersistenceParticipant();

            obj.Items.Add("Persistence Participant Extension: Before Persist");

 

            wfApp.Extensions.Add(normalObj);

            wfApp.Extensions.Add(obj);

 

            Guid persistId = wfApp.Id;

            wfApp.Run();

                       

            wfApp.Unload();

                       

 

            WorkflowApplication wfApp1 = new WorkflowApplication(new Workflow1());           

            wfApp1.InstanceStore = store;

 

            NormalExtension normalObjAfter = new NormalExtension();

            MyPersistenceParticipant objAfter = new MyPersistenceParticipant();

 

            wfApp1.Extensions.Add(normalObjAfter);

            wfApp1.Extensions.Add(objAfter);

 

            wfApp1.Load(persistId);

 

            foreach (string s in normalObjAfter.Items)

            {

                Console.WriteLine(s);

            }

 

            foreach (string s in objAfter.Items)

            {

                Console.WriteLine(s);

            }

                      

            wfApp1.ResumeBookmark("Close", null);

 

            Console.Read();

        }

 

Result

From the result screen, we can observe that the data added to the PersistenceParticipant extension before Persist operation persisted as part of workflow state information. And the data added to the normal extension before Persist operation is not available after reloading of the workflow.



Conclusion

PersistenceParticipant is a special extension for storing additional data along with the workflow state to the Instance store on Persisting a workflow. We can use normal extension for sharing data across different activities, workflow and host application. If the data needs to be persisted along with workflow state, then use the PersistenceParticipant Extension.

Page copy protected against web site content infringement by Copyscape

About the Author

Ambily.raj
Full Name: Ambily KK
Member Level: Silver
Member Status: Member,Microsoft_MVP,MVP
Member Since: 5/18/2010 1:05:25 AM
Country: India
Thanks Ambily K K http://ambilykk.com/
http://ambilykk.com/
I have over 9 years of experience working on Microsoft Technologies. I am carrying the passion on Microsoft technologies specifically on web technologies such as ASP .Net and Ajax. My interests also include Office Open XML, Azure, Visual Studio 2010. Technology adoption and learning is my key strength and technology sharing is my passion.

Login to vote for this post.

Comments or Responses

Posted by: SheoNarayan on: 1/10/2011 | Points: 25
Great going Ambily, this series of articles on WWF is really great.

Keep it up!
Posted by: Aa77 on: 1/5/2012 | Points: 25
Hi Ambily,

I am working on WWF application where my requirement is to save a List<TransactionView> in a persist workflow to show persist data in a grid. I follow your way to do this but i am getting exception while saving this.
please help me out on this

Login to post response

Comment using Facebook(Author doesn't get notification)