I recently made changes to my MVC3 Application in attempt to properly dispose of the DbContext
objects [1]. This worked great in development, but once the application was pushed to my production server, I started intermittently getting some funny exceptions which would persist until the AppPool was recycled. The exceptions can be traced back to code in my custom AuthorizeAttribute
and look like:
System.InvalidOperationException: The 'Username' property on 'User' could not be set to a 'Int32' value. You must set this property to a non-null value of type 'String'.
System.InvalidOperationException: The 'Code' property on 'Right' could not be set to a 'String' value. You must set this property to a non-null value of type 'Int32'.
(Database schema looks like this: Users: [Guid, String, ...], Rights: [Guid, Int32, ...])
It is as if some "wires are getting crossed", and the application is mixing up results from the database: trying to materialize the Right
result as a User
and vise versa.
To manage the disposal of DbContext
, I put code in to store this at a per-controller level. When the controller is disposed, I dispose the DbContext
as well. I know it's hacky, but the AuthorizeAttribute
uses the same context via filterContext.Controller
.
Is there something wrong with handling the object lifecycle of DbContext
in this manor? Are there any logical explanations as to why I am getting the crisscross exceptions above?
[1] Although I understand that it is not necessary to dispose of DbContext
objects, I recently came across a number of sources stating that it was best practice regardless.
Edit (per @MikeSW's comment)
A property of the AuthorizeAttribute
representing the DbContext
is being set in the OnAuthorization
method, when the AuthorizationContext
is in scope. This property is then later used in the AuthorizeCore
method.
Don't dispose DbContext objects. Although the DbContext implements IDisposable , you shouldn't manually dispose it, nor should you wrap it in a using statement. DbContext manages its own lifetime; when your data access request is completed, DbContext will automatically close the database connection for you.
When the controller is being disposed, call dispose on your repository and that should dispose the context. If you are using a service layer and not talking to the repository directly from the controller, then call dispose on the service which will call dispose on repo which will dispose the context.
Intuitively, a DbContext corresponds to your database (or a collection of tables and views in your database) whereas a DbSet corresponds to a table or view in your database.
Do you actually need to dispose the context?
According to this post by Jon Gallant who has been in touch with the Microsoft ADO.NET Entity Framework team:
Do I always have to call Dispose() on my DbContext objects? Nope
Before I talked with the devs on the EF team my answer was always a resounding “of course!”. But it’s not true with DbContext. You don’t need to be religious about calling Dispose on your DbContext objects. Even though it does implement IDisposable, it only implements it so you can call Dispose as a safeguard in some special cases. By default DbContext automatically manages the connection for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With