C# – Dependency Inject DbContext into MVC Controller

cdependency-injectionentity-framework

I'm having some concerns about injecting my Entity Framework DbContext into my MVC controller.

Below is a sample of my code. The way I designed this is so that I can better unit test my Controller code by injecting a real or mock DbContext.

What I'm currently planning to do is using Unity and the IDbEntities interface to inject the DbContext into the controller. Every time a new action is called from this controller,
Unity will call the controller constructor and make a new DbContext object which implements the IDbEntities interface.
That way I have a fresh context object on each new request, which I think is pretty safe.

My concern is what happens next. In the Action, I can have multiple calls to the same or different Data Service using the same DbContext object. For example, in my Index() action I can have calls to
UpdateEvent(dbContext) and then call SoftDeleteEvent(dbContext) using the same DbContext object, or even pass the same context to a different Data Service, for example UserService.LogoutUser(dbContext).

I'm not sure if all this passing around of the same DbContext object is safe.

Is it safe to pass the DbContext like this or is there a better way to extract the DbContext from the DataService into the Controller for unit testing purposes?

Controller:

public class EventsController : Controller
{    
    private IDbEntities _dbContext;

    public EventsController(IDbEntities entities)
    {
        _dbContext = entities;
    }

    public ActionResult Index()
    {
        // Hypothetical operations. In reality update and delete of the same record rarely happen in the same code branch
        var events = _eventService.AllEvents(_dbContext);
        _eventService.UpdateEvent(id, "NewName", _dbContext);
        _eventService.SoftDeleteEvent(id, _dbContext);

        return View(events);
    }
}

Data Service:

public class EventService : IEventService
{
    public IEnumerable<Event> AllEvents(IDbEntities entities)
    {
        return entities.Events.ToList();
    }

    public void UpdateEvent(Guid id, string name, IDbEntities entities)
    {
        var item = entities.Events.Find(id);
        if (item != null)
        {
            item.Name = name;
            entities.SaveChanges();
        }
    }

    public bool SoftDeleteEvent(Guid id, IDbEntities entities)
    {
        var item = entities.Events.Find(id);
        if (item != null)
        {
            item.Purged = true;
            entities.SaveChanges();
        }

        return true;
    }
}

DbContext Interface:

// This is an interface that my Entity Framework DbContext implements for Dependency Injection purposes
public interface IDbEntities
{
    DbSet<Event> Events { get; set; }
}

Best Answer

You should inject a fresh DbContext into your EventService constructor, just like you did with your EventController.

DbContext objects are lightweight, short-lived objects. Passing the DbContext from your EventController into your EventService methods creates unnecessary coupling between the classes without providing any additional benefits, and managing a DbContext's lifetime isn't the responsibility of a controller anyway.

If you don't need the DbContext in your controller (as your Controller code seems to suggest), then you don't need to inject it into the controller at all.

Class boundaries are the appropriate level of abstraction for a DbContext. In general, you shouldn't share a DbContext with other classes; just make a new one for each class instance.