Radu D
Radu D

Reputation: 3555

Entity Framework efficient query filter

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

Answers (2)

Eranga
Eranga

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

S P
S P

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

Related Questions