none
When using Repository Pattern how, when, and where to ensure a DBContext is disposed

    Question

  • On page 11 of Programming Entity Framework DBContext by Julia Lerman and Rowan Miller there is this statement:

    "It's important to ensure that resources used to perform these operations are cleaned up when the DbContext instance is no longer needed.  DbContext implements the standard .NET IDisposable interface, which includes a Dispose method that will release any such resources."

    Great advice and easy when implementing the using pattern.  But that doesn't work in the disconnected state scenario such as the Repository pattern in a MVC3 application.  Chapter 4 addresses the disconnected entities scenario; but, inexplicitly, does not address this important detail.  From my experience, doing it inside a Repository causes unexpected side effects:

    see: http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/f9e23106-52c2-4807-bb57-4e09f6c15ba2/

    You can focus on the discussion at the end of the intial post and skip all the code unless you are just curious.

    WRL


    WhiskeyRomeoLima

    Thursday, July 12, 2012 3:12 PM

Answers

  • Hi WhiskeyRomeoLima,

    Please look at the implementation of UnitOfWork in the Cotoso University tutorial below.

    public class UnitOfWork : IDisposable
        {
            private SchoolContext context = new SchoolContext();
            private GenericRepository<Department> departmentRepository;
            private GenericRepository<Course> courseRepository;
    
            public GenericRepository<Department> DepartmentRepository
            {
                get
                {
    
                    if (this.departmentRepository == null)
                    {
                        this.departmentRepository = new GenericRepository<Department>(context);
                    }
                    return departmentRepository;
                }
            }
    
            public GenericRepository<Course> CourseRepository
            {
                get
                {
    
                    if (this.courseRepository == null)
                    {
                        this.courseRepository = new GenericRepository<Course>(context);
                    }
                    return courseRepository;
                }
            }
    
            public void Save()
            {
                context.SaveChanges();
            }
    
            private bool disposed = false;
    
            protected virtual void Dispose(bool disposing)
            {
                if (!this.disposed)
                {
                    if (disposing)
                    {
                        context.Dispose();
                    }
                }
                this.disposed = true;
            }
    
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
        }

    When we instantiate an object of 'UnitOfWork' class, a context has already exist, every time we create a Resposity instance, the same context will pass to the constructor of the 'Repository' class, so it can ensure the context is the same.

    Best Regards


    Allen Li [MSFT]
    MSDN Community Support | Feedback to us

    Tuesday, July 17, 2012 5:39 AM

All replies

  • Hi WhiskeyRomeoLima,

    Glad to see you again.

    I have replied your another post (here) and provide two good articles about this issue, please refer to them. I hope it could help.

    Best Regards


    Allen Li [MSFT]
    MSDN Community Support | Feedback to us


    Monday, July 16, 2012 2:15 AM
  • I have gone through the Cotoso University tutorial.  From that tutorial -- "One way to minimize redundant code is to use a generic repository, and one way to ensure that all repositories use the same database context (and thus coordinate all updates) is to use a unit of work class." 

    Is the unit of work pattern the only way to resolve the problem of having redundant contexts?  I would like to understand the problem a little better before I implement a solution.  For example, when you load a view that a controller provides loaded with data to be modifed, you make a change, and submit the form.  Now the controller is back in charge again and saves your work and then returns a confirmation view, or some other action.  So does EF do anything behind the scenes to ensure that a submit on a form with a view provied by one context ( the get) is serviced by that same context (the post) or are contexts created willy-nilly everytime a get or post is done?

    WhiskeyRomeoLima


    WhiskeyRomeoLima

    Monday, July 16, 2012 3:09 AM
  • Hi WhiskeyRomeoLima,

    Please look at the implementation of UnitOfWork in the Cotoso University tutorial below.

    public class UnitOfWork : IDisposable
        {
            private SchoolContext context = new SchoolContext();
            private GenericRepository<Department> departmentRepository;
            private GenericRepository<Course> courseRepository;
    
            public GenericRepository<Department> DepartmentRepository
            {
                get
                {
    
                    if (this.departmentRepository == null)
                    {
                        this.departmentRepository = new GenericRepository<Department>(context);
                    }
                    return departmentRepository;
                }
            }
    
            public GenericRepository<Course> CourseRepository
            {
                get
                {
    
                    if (this.courseRepository == null)
                    {
                        this.courseRepository = new GenericRepository<Course>(context);
                    }
                    return courseRepository;
                }
            }
    
            public void Save()
            {
                context.SaveChanges();
            }
    
            private bool disposed = false;
    
            protected virtual void Dispose(bool disposing)
            {
                if (!this.disposed)
                {
                    if (disposing)
                    {
                        context.Dispose();
                    }
                }
                this.disposed = true;
            }
    
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
        }

    When we instantiate an object of 'UnitOfWork' class, a context has already exist, every time we create a Resposity instance, the same context will pass to the constructor of the 'Repository' class, so it can ensure the context is the same.

    Best Regards


    Allen Li [MSFT]
    MSDN Community Support | Feedback to us

    Tuesday, July 17, 2012 5:39 AM
  • Hi WhiskeyRomeoLima,

    Any update about this issue? If you need further help, please feel free to let me know, I will be more than happy to be of assistance.

    Best Regards


    Allen Li [MSFT]
    MSDN Community Support | Feedback to us

    Thursday, July 19, 2012 7:53 AM
  • Hi Allen,

    Thank you for your time on this and for following up.

    I am looking at the Unit of Work options versus the disconnected scenarios where the context for the get is different from the post or any N-Tier type architecture. In the disconnected scenario described in the book I referenced in my initial post, it explains options for informing the new context of the current state of each entity involved in a given transaction (replaying the changes). In the examples used in the book, the Using block still serves as the means to dispose of the context after the changes have been replayed.

    The Unit of Work approach seems to require keeping a Unit of Work class and context open on the server.  If I understand it correctly.

    In any case, I am learn the pros and cons of both approaches so we can close this issue for me



    WhiskeyRomeoLima



    Thursday, July 19, 2012 5:39 PM