Monday, August 3, 2009

Silverlight 3 & RIA Services based K2 View Flow

The customer I'm currently working for asked me to realize a POC of a custom view flow for K2 [blackpearl]. The reason for that was because they wanted to make data provided natively by K2 together with custom data coming from external sources to be exposed as a whole in a graphical business process view flow. In order to do that they needed to understand how easy and fast would have been to write an application that pulls data down from the process engine and shows that data in a graphical format on the web.
For what is concerning the UI I had no choice, they wanted the view flow to be exposed via web so Silverlight was definitively the right answer.
As far as is concerning the K2 flow data access instead, I knew that I had 2 choices:



  • To use the ViewProcessInstance method of SourceCode.Workflow.Client.Connection to retrieve an xml representation of the process instance flow (it is essentially what the OOB ViewFlow does under the hood)

  • To access directly the K2ServerLog database in order to extract the information I needed

Even if the first choice should have been the right one for many reasons:


  • Coding over data provided from a documented API should be faster than reading the same data from a partially documented database

  • What would happen at my code if K2ServerLog changed due to a K2 hotfix?

  • Why do not follow the same path that SourceCode itself followed?

I finally decided for the second one because:


  • I saw that accessing K2ServerLog directly performs better than calling K2 server to retrieve the same data

  • Accessing K2ServerLog directly instead of calling K2 server doesn't load K2 server

  • The K2ServerLog schema is not changed frequently… the actual one has pretty much the same structure it had in K2.NET 2003

  • K2ServerLog tables and schemas are documented in the K2 [blackpearl] official documentation

  • K2ServerLog is the logging - not transactional – database, thus accessing it should not disrupt K2 Server execution performances

  • I had few time to realize my POC and I knew well the structure of K2ServerLog because I already studied it before for other purposes

  • I wanted to try RIA Services in a real scenario… J

I started defining constraints (keys, foreign keys, relationships…) on a copy of K2ServerLog database (K2ServerLog itself comes with no constraints). This would have helped LINQ to SQL to create entities and associations in the appropriate manner. Obviously constraints were only needed for development and were not meant to be used at runtime. What I obtained finally is the following (I extracted below only the part that is relevant for my View Flow):





After that I created a new Silverlight Application and I enabled .NET RIA Services integration:







I added a new LINQ to SQL Classes item and I followed the wizard to make it pointing to my modified K2ServerLog database and to include the desired tables.

I finally obtained the ERM for the K2ServerLog database:






I added a new Domain Service Class item (including metadata classes). I added a custom method to the domain service in order to get a process instance and all the related entities given its id:


public _ProcInst Get_ProcInstById(Int32 procInstId)
{
DataLoadOptions loadOptions = new DataLoadOptions();

// ProcInst
loadOptions.LoadWith<_ProcInst>(p => p._Proc);
loadOptions.LoadWith<_ProcInst>(p => p._ActInsts);

// Proc
loadOptions.LoadWith<_Proc>(p => p._Acts);
loadOptions.LoadWith<_Proc>(p => p._Lines);

// Act
loadOptions.LoadWith<_Act>(a => a._Events);

// Line
loadOptions.LoadWith<_Line>(l => l._Act);
loadOptions.LoadWith<_Line>(l => l._Act1);
loadOptions.LoadWith<_Line>(l => l._LineInsts);

this.Context.LoadOptions = loadOptions;

_ProcInst procInst = (from o in Context._ProcInsts
where o.ID == procInstId
select o).First();

return procInst;
}

I decorated with the Include attribute the same properties in the appropriate metadata classes:


internal sealed class _LineMetadata
{
// Metadata classes are not meant to be instantiated.
private _LineMetadata()
{
}

[Include]
public _Act _Act;

[Include]
public _Act _Act1;

[Include]
public EntitySet<_LineInst> _LineInsts;

And that's it; I was ready to code in Silverlight!!!

And that's the result… I know it's still not too rich but I haven't spent too much time playing with effects:


No comments:

Post a Comment