How should I scope dependency injection of Entity Framework DbContext in a web app? (InstancePerHttpRequest vs SingleInstance)
Asked Answered
Q

3

8

I have read that DbContext object should be created as InstancePerHttpRequest, not SingleInstance, because of its thread-unsafe nature and it might consume too much resource between requets which makes sence. But I am using Repository objects which uses DbContext instance. Should I make them InstancePerHttpRequest or make them SingleInstance and use DependencyResolver to get the current DbContext.

What would the best object creation design be, for Autofac (or any other DI), DbContext, Repository and Service based Web application?

Another question, how expensive it is to create a different DbContext object for each repository or service for each web request (like 10-15 of them in a request)?

Quillen answered 31/8, 2012 at 0:29 Comment(2)
possible duplicate of One DbContext per web request...why?Reefer
Related: #5324647Reefer
A
11

DbContext is incredibly cheap to instantiate so I wouldn't worry too much around the time taken to get a new one.

The issue I have with scoping around DbContext isn't so much thread safety its query isolation. Because anyone can call save changes and commit the whole object graph to the database you want to make sure you only call it on a context with your specific changes.

Another key thing to understand about DbContext is that performance degrades the more items it is tracking. This means if you bind it in singleton you can cause some pretty serious performance issues. (there are ways around this but its really good to be aware of see my post on this here)

My personal preference for web apps is to bind both your context and repository in the scope of an HttpRequest. This means that only your current request thread will be able to save changes, and it also limits the amount of items you are likely to track.

Sorry a bit of my terminology probably doesn't match autofac as im a ninject man myself :)

Abscind answered 31/8, 2012 at 0:39 Comment(3)
"anyone can call save changes and commit the whole object graph". That's a thread-safety issue, isn't it? You'll simply be in serious shit when when you share a DbContext accross threads/requests.Reefer
@Reefer Yeah this absolutely applies to threading, however I would suggest that its even more extensive than just a threading issue. The risk is that even in a single threaded application if you were to query some data and muck around with it (with no intention of persisting those changes) and later reuse the context to perform an update both the update and previous changes to attached objects will be committed. This is one of the reasons its recommended to keep the scope of DbContext as small as possible (ie just your unit of work).Abscind
@Reefer in addition the performance issues with long term use of DBContext make it pretty impractical (without hand managing the tracking graph)Abscind
S
2

DbContext is your Unit of Work, and is thus never suited for SingleInstance scope. Treat it as such. Sometimes a request maps directly to a UoW, but not necessarily always. Consider this before you scope it to the request.

Scut answered 31/8, 2012 at 7:31 Comment(0)
H
0

DbContext is cheap to instantiate, so I would design it such that each service gets its own instance. 10-15 per request is fine, unless you encounter a problem you can trace back to the number of DbContexts instantiated. Anything else smells like pre-mature optimization to me.

I tried to stay DI agnostic, as I primarily use StructureMap.

Hardunn answered 31/8, 2012 at 1:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.