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; }
}