I'm hoping to finally get to the very bottom of an ongoing problem with Entity Framework DbContexts. The history of my problem is that sporadically - especially when requests come in in fast succession - my DbContext throws a variety of strange errors, including the following:
System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
System.InvalidOperationException: Internal connection fatal error.
My MVC code is based around a basic pattern where I have a base controller, which looks like this:
public class BaseController : Controller
{
protected readonly DbContext db = new DbContext();
protected override void Dispose(bool Disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
All other controllers derive from this base controller, thereby making the DbContext available as necessary to controller actions, none of which are asynchronous. The only exception is my custom authorization, which also creates a DbContext upon access and is called with virtually every controller action (via attribute):
public class MyAuthorizeAttribute : AuthorizeAttribute
{
private DbContext db;
protected override bool IsAuthorized(HttpActionContext actionContext)
{
db = new DbContext();
var user =
db.Security.FirstOrDefault(u =>
u.Id == actionContext.ControllerContext.Request.Headers.First(h =>
h.Key == "Id").Value);
return (user != null);
}
}
I've also experimented with the following to no avail:
- Removed all asynchronicity from my controller actions
- Removed lazy loading from DbContext and inserted explicit Include statements with each call
Looking through StackOverflow, other people appear to have had similar issues:
- Weird race conditions when I send high frequency requests to my datacontext
- Random errors occur with per-request DbContext
Neither answers really helped me get to the bottom of the problem, but the OP-answer of the second SO post said ("After further investigation I found out that request processing thread sometimes steals DbContext from other thread"), but I'm not sure how this really applies.
Is there something fundamentally wrong with my design? Wrapping each controller action's DbContext into a using block can't be right, even though this blog says it is - but doesn't that cause other problems, such as returning objects that are no longer attached to a DbContext (and therefore lose change tracking)...?