patterncsharpMinor
Disposing the Context in the Repository pattern
Viewed 0 times
thedisposingrepositorycontextpattern
Problem
I have a question about the Repository pattern:
Why I am not embracing each method implementation with a
Some of my methods, as
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 ConSolution
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):
Beware that this is expensive if the data set is huge, if you don't actually want all the data you queried.
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.