I am investigating using OpenAccess ORM for our new ORM tool to replace our direct ADO.NET SQL code. I have the Open Access ASK installed and I have looked at the ASP.NET MVC Forums sample application. In this application when it creates the ContextFactory class, it is created using the Unity IOC container with a ContainerControllerLifetimeManager(). This means that only one ContextFactory instance is created for the life of the application, and hence only one OpenAccessContext() is created and it lasts for the life of the application.
I tested this and verified that is true with the ASP.NET development server, and it would seem this would be a very efficient way of handling access to the database, as only one context is actually created. However how does this work when the application is deployed on a real IIS web server, for a high load site? If the site load goes up, doesn't IIS create new threads within the Application Pool in order to be able to service more requests? When that happens does a new thread get started that runs on the same HttpApplication instance, or does IIS create an entirely new HttpApplication instance for every server thread in the application pool?
It seems to me that if the methods used in the sample program work in production, that IIS must be creating an entirely new HttpApplication per thread? Since I assume OpenAccess ORM is not thread safe, like most other .NET libraries? Or am I missing something entirely?
9 Answers, 1 is accepted
Let me shed some light on the situation, when using the context object an internal static database object is created that holds the information for the model. One database object will server as the basis for more than one context. Meaning that a couple of context instances will use the same internal database object.
This is done because the metadata information describing your model is further calculated and this is not a lightweight operation.
However, there is more to the situation. Whenever a context is created it holds a cache of all the objects it is tracking. Usually the suggested practice is to have a context live as long as a request, given that the context is pretty lightweight this is okay (the slow operation is handled in the database object creation).
The problem one might face with a context that is serving more than one request is that it will retrieve object from its cache and not the database. So if there is another thread or application doing the same and modifying data, you might end up with invalid data.
I will suggest sticking to short living context instances that are created per request and having a look at our L2 cache mechanism. You can find more information on how to enable that on this help article.
I am not sure if that fully answers your question so please do not hesitate to let us know if you need more information on the matter.
the Telerik team
Thanks for the reply!
The problem is that since the sample application simple creates one long running context when the Application_Stated() function is called (because that is when the UnityContainer is created), the exact same ORM context is going to be used by ALL HttpApplication instances, and if at some point two concurrent requests are processed, there will be issues when they are both using the same ORM context.
I am not sure what the correct solution is, other than changing the controller factory to serve up a new ORM context for every thread. Any suggestions on how to fix this correctly?
You are completely correct, having a long running scope is a bad practice in web environment and we have pointed that previously in some of our KB articles and blog posts. The context must be created and disposed of on each request to the web server in order to be sure that there will be no threading issues with your data access. I will point you now to a blog post that was written some time ago, and it discusses the IObjectScope which is an old API, but you can look at this object as the context - it basically has the same role in the product - just the API is older. Here is a link to this blog post. The focus in this post are actually the ASP .NET web forms and not ASP .NET MVC, but I hope you can get the main idea from it and utilize the approach in your application without limiting yourself by the platform that you use.Regards,
the Telerik team
Specifically the sample program goes to the extend of using a context factory class and interface to it to abstract away from the actual creation of the context, however the context is only created ONCE in the lifetime of the context factory, and is also cached in all the respository instances. And since the IoC container has been set up to keep only one context factory around for the life of the IoC container (which is the lifetime of the entire application, not an application instance), then the context is going to be identical for EVERY request processed.
It would appear from my understanding of the Unity container, that the repositories are created on demand every time someone needs one, and probably only hang around per request. So the fix for this program as I see it, is to somehow make the context factory only hang around for the life of a single request (request scope in Ninject for instance), so that every request would get their own copy of the context factory.
You are perfectly write. I would like to thank you for leading us to this rather unpleasant error in the MVC Forum sample. We most certainly be fixing this problem and handling the context lifetime per request. I hope in the next release of the SDK that this matter will be resolved.
Please find you Telerik Points updated.
the Telerik team
We are planning on releasing the next version of our SDK with our SP1, however we do not have an exact timeframe for this that I can share with you.
Fortunately the MVC example has only one flaw and this is that the context object is alive as long as the application is alive which is something that we have discussed here and you should be able to work around.
Also given that OpenAccess is pretty easy to get started with (you can have a look at our Fluent Mapping Getting started tutorial) and the great tutorials over at asp.net/mvc you should have too much trouble kick-starting a project.
You can also rely on us to give you any and all advice that you might need in order to get your application up and running.
We are looking forward to hearing back from you.
the Telerik team