问题
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
?
回答1:
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!
来源:https://stackoverflow.com/questions/20023187/reexecuting-iqueryable-on-different-dbcontext-instance