EF - The context cannot be used while the model is being created exception during HTTP requests

一个人想着一个人 提交于 2019-11-28 06:25:21
Kit

Your repository is short-lived (you create it for each call to GetRoomStation() but your actual context appears to be long-lived (RoomServiceStation.Context property). This means that every call to your web application is going to use the same context.

This is the "EF in an N-tier" scenario where you're trying to keep something stateful around (the context) in the architecturally stateless model of a web application. All those requests are being channeled to the same context on different threads and you're getting a race condition.

One thread could be kicking off first-time initialization of your context in response to a request, and another comes in attempting to use the context. The second request thinks the context is ready for use and you get this exception. You may even get this if you have multiple contexts trying to "spin up" at the same time as suggested in another SO thread.

You can do a few things. You could try pessimistic locking around access to your context, but you're putting in an unnecessary bottleneck. You could try creating some sort of "before clients are calling me, initialize the context" code, but you have to find a good place to do this, perhaps using the "brute force" method suggested in an MSDN thread.

A better thing to do is to simply create a new context for every request to your back-end service. There is some overhead, yes, but minimal. The overhead is probably less likely to kill performance than pessimistic locking, and won't be subject to app pool recycle events scaling out your web app on a farm and so on.

If you're relying on change tracking or other stateful nature of a context, you will lose this benefit. In this case, you're going to have to come up with a different mechanism for tracking and minimizing database hits.

From an MSDN article this is summed up (emphasis mine):

If you serialize entities from one tier to another, the recommended pattern is to keep the context around on the mid-tier only long enough for a single service method call. Subsequent calls will spin up a new instance of the context to complete each task.

A thread on EF/WCF/N-tier may also give you some insights, and Jorge's blog post #5 talks about EF in N-Tiers (the whole series might be a good read). And by the way, I've run into the exact same thing: many clients hitting the context at the same time, resulting in this issue.

I encountered this error and have appeared to have solved it by providing an override to the Dispose() method in the controller. It would appear that force closing the database connection before attempting to open an new one subverts this error.

protected override void Dispose(bool disposing)
{
   if(disposing)
   {
        _fooRepository.Dispose();
   }
   base.Dispose(disposing);
}

This seems as one of two things, a race condition of some sorts or a "context scoping" issue. You should make sure that the context is being initialized in a thread safe way and that the context is not being accessed by different threads to prevent race conditions. A hard to catch cause of this error is also the accessing of the model itself in the OnModelCreation override.

I experienced this problem today. The problem was that I was accidentally using the same instance of my DbContext across requests. The first request would create the instance and start to build up the model, and the second request would come in and try to retrieve data whilst it was still building up.

My mistake was silly. I accidentally used HttpContext.Current.Cache instead of HttpContext.Current.Items :)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!