gbro3n
gbro3n

Reputation: 6967

What is the correct way to manage dependency injection for Entity Framework ObjectContext in ASP.NET MVC controllers?

In my MVC controllers, I'm using an IoC container (Ninject), but am not sure how to best use when it comes to the Entity Framework ObjectContext.

Currently, I'm doing something like:

using(var context = new MyObjectContext())
{
     var stuff = m_repository.GetStuff(context);
}

This is the best way to manage from the point of view of keeping the database connection open for the shortest time possible.

If I were to create the ObjectContext via Ninject on a per request basis, this obviously keeps the database connection open for too long.

Also the above code would become...

var stuff = m_repository.GetStuff(m_myObjectContext);

(And when would I dispose of the context...?)

Should I be creating a factory for the ObjectContext and pass that in via DI? This would loosen the coupling, but does this really help with testability if there is no easy means of maintaining an interface for the ObjectContext (that I know of)?.

Is there a better way? Thanks

Upvotes: 2

Views: 783

Answers (1)

Steven
Steven

Reputation: 172835

This is the best way to manage from the point of view of keeping the database connection open for the shortest time possible.

If I were to create the ObjectContext via Ninject on a per request basis, this obviously keeps the database connection open for too long.

Entity Framework will close the connection directly after the execution of each query (except when supplying an open connection from the outside), so your argument for doing things like this does not hold.

In the past I used to have by business logic (my command handlers to be precise) have control over the context (create, commit, and dispose it), but the downside is that you need to pass on this context to all other methods and all dependencies. When the application logic gets more complex, this results in less readable, less maintainable code.

For that reason I moved to a model where the unit of work (your MyObjectContext) is created, committed, and disposed outside the control of the business logic. This allows you to inject the unit of work into all dependencies and reuse the same unit of work for all objects. Downside is that this makes your DI configuration a bit harder. Some things your need to make sure of:

  1. The unit of work must be created as per web request or within a certain scope.
  2. The unit of work must be disposed at the end of the request or scope (although it is probably not a problem when the DbContext is not disposed, since the underlighing connection is closed and DbContext does not implemente a finalizer).
  3. You need to explicitly commit the unit of work, but you can't do this at the end of the web request, since at that point you have no idea whether it is safe to commit (since you don't want to commit when your business logic threw an exception, but at the end of the request there is no way to correctly detect if this actually happened).

One tip I can give you is to model the business logic in the system around command handlers, since this allows you do define a single decorator that handles the transactional behavior (committing the unit of work and perhaps even running everything in a database transaction) at a single point. This decorator can be wrapped around each handler in the system.

I must admit that I have no idea how to register generic types and generic decorators with Ninject, but you'll probably get an answer quickly when asking here at Stackoverflow.

Upvotes: 3

Related Questions