16

I am using PredicateBuilder to create a search/filter section in my action. Here it is:

    [HttpPost]
    public ActionResult Test(int? cty, string inumber, int? page)
    {

        var lstValues =
            db.TableName.Include(x => x.Table1)
                .Include(x => x.Table2)
                .Include(x => x.Table3)
                .ToList();

        var predicate = PredicateBuilder.True<TableName>();

        if (!string.IsNullOrWhiteSpace(inumber))
        {
            predicate = predicate.And(x => x.Inumber == inumber);
        }

        if (!string.IsNullOrWhiteSpace(cty.ToString()))
        {
            predicate = predicate.And(x => x.CtyID == cty);
        }

        if (predicate.Parameters.Count > 0)
        {
            lstValues = db.TableName.AsExpandable().Where(predicate).ToList();
            Session["Paging"] = lstValues;
            ViewBag.Paging = lstValues.ToPagedList(page ?? 1, 2);
            return View(lstValues.ToPagedList(page ?? 1, 2));
        }
        else
        {
            return View(lstValues.ToPagedList(page ?? 1, 2));
        }
    }

Under this line PredicateBuilder.True<TableName>(); I get a green squiggly saying

PredicateBuilder.True() is obsolete. Use PredicateBuilder.New instead.

But I have tried PredicateBuilder.New<T> and my predicate always gets a value of 1 even if I don't have any values coming in for the parameters, so cty, and inumber are null. This returns me an empty table.. when it should be returning all records by entering the else statement with return View(lstValues.ToPagedList(page ?? 1, 2));.

When I use PredicateBuilder.True<T> I get all records returned when all of the parameters are null.

Any idea on why that is? Any help is appreciated.

Grizzly
  • 5,873
  • 8
  • 56
  • 109

2 Answers2

25

var predicate = PredicateBuilder.New<TableName>(); is equivalent to Expression<Func<TableName, bool>> predicate = item => false;

What you want instead is PredicateBuilder.New<TableName>(true); to change the default behaviour to include, rather than exclude.

Johannes Kommer
  • 6,401
  • 1
  • 39
  • 45
  • Ahh that was it! I don't know why I didn't peek the definition and see that the parameter for the overload was `bool defaultExpression`.. but thank you. – Grizzly Jan 11 '17 at 13:05
1

PredicateBuilder.New and PredicateBuilder.True looks similar but are completly different.

PredicateBuilder.True starts your predicate with the condition True. That means if you link the starter predicate PredicateBuilder.True with OR operator then the final result will be always true whatever the next condition. Conversely, if you initiate the predicate with PredicateBuilder.False linked to AND operator then the final result will be false whatever the next condition.

PredicateBuilder.New is different because is just a starter which will be ignored when you will link the next condition.

PredicateBuilder.New(false) AND true has true as final result. PredicateBuilder.New(true) OR false has false as final result.

var myList = new List<Product>
{
  // 2 products in my list
}

var filtersPredicate = PredicateBuilder.New<Product>(false);
filtersPredicate = filtersPredicate.And(p => true);
var filtered = myList.Where(filtersPredicate.Compile()).ToList();
// 2 products returned in filtered

BUT

var filtersPredicate = PredicateBuilder.False<Product>();
filtersPredicate = filtersPredicate.And(p => true);
var filtered = myList.Where(filtersPredicate.Compile()).ToList();
// 0 products returned in filtered