Detect context in Self-hosted Web Api

753 Views Asked by At

In my current project I have a windows service that periodically runs tasks (TopShelf/Quartz.net). Instead of creating a separate project for a web service I want to add this to the windows service using the self-hosting features available in OWIN. This also has the added benifit of not needing to deploy in IIS.

When I'm going to implement my Data Access Layer (DAL) I'll be getting into problems however.

All my database actions are done within a UnitOfWork that is stored in a request state and in the end there is a commit/rollback. The context determines the lifecycle of the UnitOfWork (request state). In a console app I would use a PerThreadRequest state. In a web environment I have a PerHttpRequestState. This would mean that the scope of the UnitOfWork is per thread or per HttpRequest.

In my current project however I have the mix of both console (Quartz jobs) and web (web api calls). These both need to use the DAL but aren't able to use the same request state as it's another context.

I could solve this manually. When using the DAL from the quartz jobs, have it use the PerThreadRequestState and when using the DAL from web api calls use the PerHttpRequestState but this is a messy solution. When using the DAL it should detect in wich context it is operating and react accordingly.

But how would I go about detecting the context?

1

There are 1 best solutions below

2
On

I would suggest something like this, using Castle Windsor (although the principle is the same with other IOC/DI frameworks)

if(HttpRuntime.AppDomainAppId != null) //it's a web app
{
    container.Register(
         Component.For<IUnitOfWork>().ImplementedBy<PerHttpRequestState>());
}
else //it's a windows app
{
    container.Register(
         Component.For<IUnitOfWork>().ImplementedBy<PerThreadRequestState>());
}

Having said that, there are caveats in using a UoW on a thread lifestyle:

  • Firstly, you will have to make sure that your UoW is thread safe (what happens if two or more jobs end up accessing the UoW at the same time?)
  • More importantly, Quartz.NET uses a ThreadPool internally so it will not necessarily create a new thread every time a job is launched, but reuse an existing one. This can lead to leakage; your UoW can be de-facto shared between jobs. What you may want is to use a custom PerQuartzJob lifestyle.

Both of these, however, depend on what sort of usage you intend to put your quartz service through. If you don't have many, long-running, potentially overlapping CRUD jobs, then they are less of a concern.