Reputation: 3555
In my mvc site I use EF 4.1 for data access . Now I develop product search functionality. The method signature for getting filtered products is:
PagedList<Dress> GetDressesPage<TKey>(int page, int dressesPerPage, Func<Dress, bool> selection, Func<Dress, TKey> order, SortDirection direction);
and the way in which I get the products is:
dresses = _context.Dresses.Where(selection).OrderBy(order).Skip(page * dressesPerPage).Take(dressesPerPage).ToList();
The problem is with the function selection. I would like to be able to construct that by appending different conditions. Now I am constructing that using some if clauses for each combination of parameters ... but that gets too complex.
Do you know a simpler way in which I could pass a filter as a parameter?
Upvotes: 1
Views: 1783
Reputation: 32447
Use the Predicate Builder. Replace the Func<Dress, bool>
with Expression<Func<Dress, bool>>
. Otherwise the queries will turn into LINQ-to-Objects.
var predicate = PredicateBuilder.True<Dress>();
if (!string.IsNullOrEmpty(name))
{
predicate = predicate.And(d => d.Name.Contains(name));
}
dresses = _context.Dresses.Where(predicate).OrderBy(order)
.Skip(page * dressesPerPage).Take(dressesPerPage).ToList();
Upvotes: 4
Reputation: 4643
a perfect library for that is "LinqKit".
Example usage:
public static IEnumerable<DressItem> QueryDresses(FashionEntities ctx, Expression<Func<dresses, bool>> predicate)
{
var query = (from dress in ctx.dresses
.AsExpandable()
.Where(predicate)
select new DressItem {
id = dress.Id,
name = dress.Name,
price = dress.Price
};
return query;
}
As you can see, the method accepts a predicate which you can construct in the calling method as follows:
Expression<Func<dresses, bool>> predicate = d => d.Price > 1000;
if (lalalala == llalala) {
predicate = d => d.Price > 2000;
}
var result = new List<DressItem>();
using (var ctx = new FashionEntities())
{
var dresses = QueryDresses(ctx, predicate.Expand());
result = dresses.ToList();
}
Upvotes: 0