RSS

Category Archives: .Net

K2 and Entity Framework

I’m taking a quick break from WF4 to blog about some fun we’re having with Entity Framework and K2. I’ll get back to WF4 straight away…

Our situation is as follows: Our workflow directly references a class library (our application’s business layer) and the class library uses Entity Framework to access the application database. The first event in our workflow is a code event which loads up some config entries from this class library (which in turns gets them from our database) and then assigns a task to the user. We’re starting our workflows through the API and we’re doing it synchronously, which means the method doesn’t return until the K2 process reaches a stable state like a client event.

Here’s the issue – the first call to start a process instance takes 35 seconds. After that they are all quick, but after a bit of inactivity it takes 35 seconds again.

To understand what’s happening you need to understand the inner workings of Entity Framework, K2 and AppDomains. The actual cause of the performance issue is Entity Framework. I won’t go into all the details (because we don’t need them) but when you first query a database using Entity Framework a model needs to be created. This takes a lot of time. There is also some connection pooling, which also takes time. The important point here is that the model and the connection pool are cached and kept alive within the context of an AppDomain.

To make it more complicated, K2 has designed their application such that each process definition has it’s own AppDomain (which is of course the correct design decision). This means that if you have 2 different process definitions referencing the same class library you will have 2 AppDomains, 2 cached models, 2 connection pools. K2 also unloads and reloads these AppDomains after 15 minutes of inactivity, so if nothing happens with ProcessA for 16 minutes and you start a new one, you’re going to see that long delay.

So what can you do? Unfortunately, not much. I tried hosting our class library in a WCF service in the hope that this would keep the model cached outside of our K2 process’ AppDomain but it doesn’t work that way. You can’t use a ‘Keep Alive’ script because the script would need to be run in the same AppDomain as the model, and unless you’re going to build that into each of your K2 processes that’s not going to work. You can, however, try one of the following options:

  1. Start your processes asynchronously. We may have to go this route.
  2. Set the AppDomainUnload timeout value to something greater than 15 minutes. To do this you set the “AppDomainUnload” setting in the \Host Server\bin\K2Server.setup file on the K2 server to something like 8 hours: <AppDomainUnload Minutes=”480″ />

Setting AppDomainUnload to a value of “0” turns off AppDomain unloading completely, but don’t ever do this or you will run into memory usage problems.

I hope this helps someone.

 
2 Comments

Posted by on January 25, 2012 in .Net, K2 API

 

Referencing dll’s from your K2 process

I’ve been having a lot of fun (not really) working with external dll references from K2 processes. There’s a light at the end of the tunnel but it helps to know what’s going on behind the scenes when you reference a dll from a process.

Here’s my situation: I needed to integrate a very complex hierarchy of dll’s so that I could access application data from the process (and wrapping them in a service wasn’t an option for me). Obviously I didn’t want to add references to all the dll’s (there are many) so I came up with a great idea – I’d add a class library which references all these dll’s (kind of a proxy class) and then reference only this one dll from my process. Great idea, yes. Successful, no.

To explain why it didn’t work I’ll first explain what happens when you reference a dll from a process. You’ll notice that ‘copy local’ is checked by default. This is because when you deploy the workflow, the referenced dll is sucked into the process and deployed to the database along with the process definition. Then, when you start the first instance of this process, the process definition is unpacked and a temporary folder is created in the HostServer\bin folder, and your referenced dll is copied into the temporary folder. (Side note: note how nicely versioned this is. If you have different version of the process running, each version will have it’s own temporary folder with the version of the dll that the process was deployed with. There’s an excellent blog about this here if you can access it).

So here’s the first important point: only the referenced dll is deployed with the workflow. NONE of the dll’s the referenced dll relies on are deployed, even of those dependent dll’s have ‘copy local’ set to true. So in my case I had a proxy class deployed but the actual dll’s I was trying to use were nowhere to be seen.
So what’s the best thing to do? You have 3 options:

  • Reference all the dll’s from the process (not my preferred option)
  • Copying the dll’s to K2’s bin folder
  • Deploying the dll’s to the GAC
  • Overall deploying to the GAC is your best option if you can. Or of course you can wrap the dll’s up in a service – this would have been the cleanest option but in my case this option wasn’t available because we needed to tweak every little bit of performance out of the system that we could.

     
    5 Comments

    Posted by on March 10, 2011 in .Net, K2 Workflows