Search code examples
c#.netasp.net-mvc-5unity-containeridisposable

Proper way of dispose a database context with unity


I am using unity and dependency injection and currently, I am a bit confused with the disposal of the connection.

I will give an example hoping that I explain it correctly :)

I have a controller that uses a service:

public class CompaniesController : IDatabaseController
    {
        private readonly ICompaniesService _companiesService;
        public CompaniesController(ICompaniesService companiesService)
        {
         _companiesService = companiesService;
        }
    }

And the service is registered to the UnityConfig as:

container.RegisterType<ICompaniesService, CompaniesService>(new HierarchicalLifetimeManager());

*** I read that if I use IDisposable, then HierarchicalLifetimeManager is mandatory.

The service that implements the interface(I know that database connection can also be injected but for reasons that are beyond the scope of the question please ignore it) is like this:

public class CompaniesService : ICompaniesService
    {
        private readonly DatabaseContext _db = Helpers.GetDatabaseContextForRequest();

        /// <summary>
        /// Returns all employee of a company
        /// </summary>
        /// <param name="company_id">The id of the company</param>
        /// <returns>A collection of EmployeeDAP</returns>
        public IEnumerable<EmployeeDAP> GetCompanyEmployees(int company_id)
        {
            var employees = CompaniesRepository.GetCompanyEmployees(company_id);
            return employees;
        }
}

Here comes the question. Should I implement also the IDisposable interface to the service and dispose of the database connection or does GC come and clean the mess?

If I have to manually dispose of the connection should I use the Dispose Pattern or

public void Dispose()
        {
            ((IDisposable)_db).Dispose();
        }

is sufficient?

Thanks in advance

Update:

The helper method is the following one:

try
            {
                DatabaseContext db = (DatabaseContext)getRequestValue(name);
                if (db == null || !db.Database.Exists())
                {
                    db = new DatabaseContext();
                    setDatabaseContextForRequest(db, name);
                }
                return db;
            }
            catch (Exception)
            {
                return new DatabaseContext();
            }

where new DatabaseContext inherits from DbContext of EF.


Solution

  • I think making the services to dispose the DatabaseContext is giving too much responsibility to the services.

    I would move the DatabaseContext provisioning from the Helpers class to Unity, registering it using a PerRequestLifetimeManager.
    Using Unity as the lifetime manager, you would get a DatabaseContext that spans across the HTTP request, approximating the HTTP request lifetime to the lifetime of the DatabaseContext.

    This approach will allow you to avoid having the services take ownership of the DatabaseContext lifetime, keeping all the cleanup logic and ownership in the Unity container. Additionally you will be able to share the DatabaseContext instance safely between services in a single request because the DatabaseContext is disposed only at the end of the request.

    Lastly, rembember that once you dispose something you cannot use it again so you have to improve Helpers.GetDatabaseContextForRequest() to recreate the DatabaseContext if it is disposed.