HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Disposing the Context in the Repository pattern

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thedisposingrepositorycontextpattern

Problem

I have a question about the Repository pattern:

public abstract class RepositoryBase : IDisposable, IRepository where T : class, IEntity
    {
        /// 
        /// For iterations using LINQ extension methods on the IQueryable and IEnumerable interfaces
        /// it is required that the context which was used to make the query was not disposed before the iteration
        /// otherwise it will throw an exception
        /// 
        private Context _context;

        protected Context Context
        {
            get { return _context ?? (_context = new Context()); }
        }

        public virtual void AddOrUpdate(T entity)
        {
            var dbSet = Context.Set();

            if (dbSet.Contains(entity))
                entity.ChangeDateTime = DateTime.Now;
            else
                entity.AddeDateTime = DateTime.Now;

            Context.Set().AddOrUpdate(entity);
            Context.SaveChanges();
        }

        public virtual void Delete(T entity)
        {
            Context.Set().Remove(entity);
            Context.SaveChanges();
        }

        public void Drop()
        {
            var dbSet = Context.Set();

            foreach (var entity in dbSet)
                dbSet.Remove(entity);

            Context.SaveChanges();
        }

        public virtual IQueryable Find(Expression> predicate)
        {
            return Context.Set().Where(predicate);
        }

        public IEnumerable GetAll()
        {
            return Context.Set();
        }

        public void Dispose()
        {
            if (_context != null)
            {
                _context.Dispose();
                _context = null;
            }
        }
    }


Why I am not embracing each method implementation with a using and disposing the Context as soon as the query is done?

Some of my methods, as Find and GetAll return collections. I would want to be able to iterate through them using LINQ, only this is not possible if the Con

Solution

My question is about why I am not embracing each method implementation with a using and disposing the Context as soon as the query is done.
Some of my methods, as Find and GetAll return collections. I would want to be able to iterate through them using LINQ, only this is not possible if the Context is disposed, as it would be in the original Repository model.

A Linq enumerable isn't enumerated when it's created: it's enumerated when you try to work with it.

If we want to dispose the context within each each method, I think you can do that by realizing the data, i.e. by reading it all into a concrete object such List or EnumerableQuery, before you dispose the context ... something like this (untested code ahead):

public IEnumerable GetAll()
{
    using (Context context = new Context())
    {
        IEnumerable enumerable = context.Set();
        // enumerate into a List before disposing the context
        List list = new List(enumerable);
        return list;
    }
}

public virtual IQueryable Find(Expression> predicate)
{
    using (Context context = new Context())
    {
        IEnumerable enumerable = context.Set().Where(predicate);
        // enumerate into a EnumerableQuery before disposing the context
        // see https://stackoverflow.com/a/6765404/49942 for further details
        EnumerableQuery queryable = new EnumerableQuery(enumerable);
        return queryable;
    }
}


Beware that this is expensive if the data set is huge, if you don't actually want all the data you queried.

Code Snippets

public IEnumerable<T> GetAll()
{
    using (Context context = new Context())
    {
        IEnumerable<T> enumerable = context.Set<T>();
        // enumerate into a List before disposing the context
        List<T> list = new List<T>(enumerable);
        return list;
    }
}

public virtual IQueryable<T> Find(Expression<Func<T, bool>> predicate)
{
    using (Context context = new Context())
    {
        IEnumerable<T> enumerable = context.Set<T>().Where(predicate);
        // enumerate into a EnumerableQuery before disposing the context
        // see https://stackoverflow.com/a/6765404/49942 for further details
        EnumerableQuery<T> queryable = new EnumerableQuery<T>(enumerable);
        return queryable;
    }
}

Context

StackExchange Code Review Q#40038, answer score: 4

Revisions (0)

No revisions yet.