I'm creating a repository layer to encapsulate DbContext.
I would like to expose a fluent interface for building query, and dispose and create a new DbContext every time after a query request is sent:
var repo = new EntityRepository();
repo = EntityRepository.FilterByAge(30).FilterByGender("Male");
var people = repo.GetPeople();
// GetPeople() should send the request, get the result, then dispose
// the old DbContext and create a new one
repo = repo.FilterByOccupation("Programmer");
var programmers = repo.GetPeople();
// the age and gender filters should still apply here
Currently in my EntityRepository, I have a private DbContext and a IQueryable. In the Filter methods, I append the Linq methods onto the IQueryable. Then after finishing a request, I do:
db.Dispose();
db = new EntityContext();
But this does not work when I try to do another request. It says the DbContext has been disposed.
How do I keep the same query for a new DbContext?
I ended up keeping a list of "filters", which are anonymous functions that takes in IQueryable and return IQueryable. Then I apply them on a short-live DbContext :
Repository:
private IList<Func<IQueryable<Person>, IQueryable<Person>>> filters;
public Repository FilterByAge(int age)
{
var _filters = new List<Func<IQueryable<Person>, IQueryable<Person>>>(filters);
_filters.Add(q => q.Where(e => e.Age == age));
return new Repository(_filters);
}
public Repository OrderByName()
{
var _filters = new List<Func<IQueryable<Entity>, IQueryable<Entity>>>(filters);
_filters.Add(q => q.OrderBy(e => e.Name));
return new Repository(_filters);
}
private IQueryable<Person> ApplyFilters(AppContext db)
{
var result = db.People;
foreach (var filter in filters)
{
result = filter(result);
}
return result;
}
public IEnumerable<Person> GetPeople()
{
IEnumerable<Person> people;
using (var db = new AppContext())
{
people = ApplyFilters(db).ToList();
}
return people;
}
Usage
private Repository repo = new Repository();
var peopleOfThirty = repo.FilterByAge(30);
var orderedByName = peopleOfThirty.OrderByName();
if (wantOrder)
{
return peopleOfThirty.GetPeople();
}
else
{
return orderedByName.GetPeople();
}
It works for my purposes. However, please let me know if there is any problem doing it this way. Thanks!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With