Ok, I am new to DI & utilizing an IoC container. I am writing a Prism & Unity application for WPF.
I would like to instantiate an instance of more than one DBContexts and pass it to each of my viewmodels that consume it. I have deliberately left out a Repository class because I feel like the CRUD from EF is sufficient and it is only me working on this application.
I know I can initialize the DBContext in each of the ViewModels, but then I would have multiple instances of sometimes the same DBContext, I feel as though that is a bad practice and would have significant overhead.
I have googled this for the past few days and find my self a bit more confused.
Your guidance will be appreciated.
So the direct answer is that most (maybe all) DI containers support the ability to specify the object lifetime when you register that object. Usually this is done either by registering a singleton instance or registering a type and specify that it have an ‘application’ lifetime, i.e., the object lives for the entire life of the application.
That being said, you typically do not want your Entity Framework context to have an application lifetime.
I feel as though that is a bad practice and would have significant overhead.
Actually, the opposite is true – it is considered best practice for your EF context to live only as long as necessary. According to Microsoft the overhead associated with building the context model should be minimal:
There is some cost involved in discovering the model, processing Data Annotations and applying fluent API configuration. To avoid incurring this cost every time a derived DbContext is instantiated the model is cached during the first initialization. The cached model is then re-used each time the same derived context is constructed in the same AppDomain. Model caching can be turned off by setting the CacheForContextType property on ModelBuilder to ‘false’ in the OnModelCreating method.
And again here (emphasis mine):
Entity Framework’s contexts are meant to be used as short-lived instances in order to provide the most optimal performance experience. Contexts are expected to be short lived and discarded, and as such have been implemented to be very lightweight and reutilize metadata whenever possible. In web scenarios it’s important to keep this in mind and not have a context for more than the duration of a single request. Similarly, in non-web scenarios, context should be discarded based on your understanding of the different levels of caching in the Entity Framework. Generally speaking, one should avoid having a context instance throughout the life of the application, as well as contexts per thread and static contexts.
In fact, creating a context that lives for the entire life of your application can be problematic due to object caching which can cause your context to grow quite large:
By default when an entity is returned in the results of a query, just before EF materializes it, the ObjectContext will check if an entity with the same key has already been loaded into its ObjectStateManager. If an entity with the same keys is already present EF will include it in the results of the query. Although EF will still issue the query against the database, this behavior can bypass much of the cost of materializing the entity multiple times.
The more you use an ObjectContext, generally the bigger it gets. This is because it holds a reference to all the Entities it has ever known about, essentially whatever you have queried, added or attached. So you should reconsider sharing the same ObjectContext indefinitely
You said:
I know I can initialize the DBContext in each of the ViewModels, but then I would have multiple instances of sometimes the same DBContext.
I would argue that if your ViewModels are long lived that scoping your DBContext to the life of the ViewModel may still be too long (due to object caching). The best approach is to identify units of work within your ViewModel and scope the life of your DBContext to those.
Another option would be to disable object caching.