2

In many basic examples I see the using block wrapped around DbContext usage like so:

using (var context = new MyDbContext()) 
{     
    // Perform data access using the context 
}

It makes sense, because a 'new' instance is being created, so you want to dispose of this once you are finished with it.

Using DI

However in a number of projects I am working with, I am seeing DbContext being injected into repositories and service layers like this:

public class FileRequestService : IFileRequestService
{
    private readonly MyDbContext _myDbContext;

    public FileRequestService(MyDbContext myDbContext)
    {
        _myDbContext = myDbContext;
    }

    public FileRequest SaveFileRequest(FileRequest fileRequest)
    {
        fileRequest.Status = FileRequestStatus.New;
        //...
        //...
        var fr = _myDbContext.FileRequests.Add(fileRequest);
        _myDbContext.SaveChanges();
        return fr;
    }
}

And configured in the DI container like this:

container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();

container.Register<MyDbContext>(Lifestyle.Singleton);

Question 1

Is it OK that there is no using statement being used here, as it is presumably being disposed of once the web request dies?

Using DI/UoW

Similar scenario for the unit of work pattern, I am seeing this:

public class RecordController : Controller
{
  private readonly IUnitOfWork _unitOfWork;

  public RecordController(IUnitOfWork unitOfWork)
  {
      _unitOfWork = unitOfWork;
  }

  [HttpPost, ActionName("Index")]
  public PartialViewResult Search(SearchQueryViewModel searchQueryViewModel)
  {    
      var deptId =
      _unitOfWork.DepartmentRepository.Get(x => x.DepartmentCode == searchQueryViewModel.code)
      .Select(s => s.DepartmentId)
      .FirstOrDefault();
       //...                
   }
}

Which is configured in the container like so:

container.Register<IUnitOfWork, UnitOfWork>(Lifestyle.Scoped);
container.Register<IGenericRepository<Department>, GenericRepository<Department>>(Lifestyle.Scoped);

And DbContext is being injected into the constructor of the UoW class as normal.

Question 2

Again is it OK that there is no using statement being used here or should I implement the IDisposable interface on the UoW class and do something like this:

using (_unitOfWork)
{    
  var deptId =
  _unitOfWork.DepartmentRepository.Get(x => x.DepartmentCode == searchQueryViewModel.code)
  .Select(s => s.DepartmentId)
  .FirstOrDefault();
  //...
}
JsonStatham
  • 8,163
  • 26
  • 88
  • 160
  • 3
    If resource is registered in DI container, especially scoped (like web request scoped) - there is no need to dispose it manually, because it will be disposed when web request ends. By the way, it's bad to register MyDbContext as Singleton (like you do in your first example). – Evk Feb 06 '17 at 10:39
  • I have seen this suggestion a lot, however when i change my db context to be scoped, child dependencies stop coming through and are instead null, resulting in errors all over the place. I don't understand why as I have not disabled lazy loading – JsonStatham Feb 07 '17 at 15:03
  • Well maybe you should post another question about this, with more details. But registering EF context as singleton in web application will lead you to much more troubles, for sure. – Evk Feb 07 '17 at 15:04
  • To be honest i think this is due to UoW rather than singleton, im not sure it is lazy loading. – JsonStatham Feb 07 '17 at 15:21

1 Answers1

2

Simply put, whoever creates an instance should be the one responsible for calling its dispose method.

On Question 1: I would personally avoid the use of singletons for the DbContext. A quick search on google shows many articles/Stackoverflow questions but here is the first one in line : Entity Framework Context in Singleton In your current case - it will not get disposed, never. It is registered in a singleton scope which means you would have a single instance that will kept as long as the container is. (simple injector scopes help page for reference - http://simpleinjector.readthedocs.io/en/latest/lifetimes.html )

On Question 2: Most containers would call the dispose method of all IDisposable instances once they leave their scope. If you call dispose yourself earlier, you might end up disposing the instance that is going to be provided as a dependency somewhere else. Doing so will result in the other code trying to use that very same disposed instance...

EDIT: if the scope is not controlled by the DI framework, you would have to call dispose on your own of course. But this is not the case that we are discussing

Community
  • 1
  • 1
Stefan Georgiev
  • 152
  • 1
  • 4