Print Page | Close Window

Dynamically building Predicate description

Printed From: IdeaBlade
Category: DevForce
Forum Name: DevForce 2010
Forum Discription: For .NET 4.0
URL: http://www.ideablade.com/forum/forum_posts.asp?TID=2037
Printed Date: 10-Jun-2026 at 5:03pm


Topic: Dynamically building Predicate description
Posted By: BillG
Subject: Dynamically building Predicate description
Date Posted: 30-Jul-2010 at 3:38pm

I have a search form that has 5 fields on it; ssn, cardno,employeeno, firstname, lastname. The user could fill in anyone of the fields and click find to find the member.

 
I am collecting the filled-in fields with a Query Object and passing it to my FetchMembers() method in my viewmodel.
 
Here is the code so far.
 

PredicateDescription p1 = null;

PredicateDescription p2 = null;

PredicateDescription p3 = null;

PredicateDescription p4 = null;

PredicateDescription p5 = null;

if(q.SSN != string.Empty)

p1 = PredicateBuilder.Make(typeof(Member), "SocSecNo", FilterOperator.IsEqualTo, q.SSN);

if(q.LastName != string.Empty)

p2 = PredicateBuilder.Make(typeof(Member), "LastName", FilterOperator.StartsWith, q.LastName);

if(q.FirstName != string.Empty)

p3 = PredicateBuilder.Make(typeof(Member), "FirstName", FilterOperator.StartsWith, q.FirstName);

if(q.EmployeeNo != string.Empty)

p4 = PredicateBuilder.Make(typeof(Member), "EmployeeNo", FilterOperator.IsEqualTo, q.EmployeeNo);

if(q.CardNo != 0)

p5 = PredicateBuilder.Make(typeof(Member), "CardNo", FilterOperator.IsEqualTo, q.CardNo);

var query = PredicateBuilder.FilterQuery(entityManager.Members, p1.And(p2).And(p3).And(p4).And(p5));

but not all the PredicateDescription objects might have values. How do I dynamically combine the p1, p2, p3 only if they are not null.
 
Bill
 



Replies:
Posted By: GregD
Date Posted: 02-Aug-2010 at 11:52am
There is a static overload on PredicateBuilder

public static Expression<Func<T, Boolean>> And<T>(params Expression<Func<T, Boolean>>[] expressions) {


               that allows an arbitrary array of Expression<…> to be anded together. So code would look something like…

List<Expression<Func<Member, bool>> expressions = new List<Func<Member, bool>>();

if(q.SSN != string.Empty)
expressions.Add(PredicateBuilder.Make(typeof(Member), "SocSecNo", FilterOperator.IsEqualTo, q.SSN));
if(q.LastName != string.Empty)
expressions.Add(PredicateBuilder.Make(typeof(Member), "LastName", FilterOperator.StartsWith, q.LastName));
if(q.FirstName != string.Empty)
expressions.Add(PredicateBuilder.Make(typeof(Member), "FirstName", FilterOperator.StartsWith, q.FirstName));
var newExpr = PredicateBuilder.And(expressions.ToArray());
var query = PredicateBuilder.FilterQuery(entityManager.Members, newExpr);



Posted By: BillG
Date Posted: 03-Aug-2010 at 1:18pm
Here is the new revised method but I am getting a syntax error after the comma in the word Member

public void FetchMembers(MemberQuery q)

{

List<Expression<Func<Member, bool>> expressions = new List<Func<Member, bool>>(); //Error on this line.

if(q.SSN != string.Empty)

expressions.Add(PredicateBuilder.Make(typeof(Member), "SocSecNo", FilterOperator.IsEqualTo, q.SSN));

if(q.CardNo != 0)

expressions.Add(PredicateBuilder.Make(typeof(Member), "CardNo", FilterOperator.IsEqualTo, q.CardNo));

if(q.EmployeeNo != string.Empty)

expressions.Add(PredicateBuilder.Make(typeof(Member), "EmployeeNo", FilterOperator.IsEqualTo, q.EmployeeNo));

if(q.LastName != string.Empty)

expressions.Add(PredicateBuilder.Make(typeof(Member), "LastName", FilterOperator.IsEqualTo, q.LastName));

if(q.FirstName != string.Empty)

expressions.Add(PredicateBuilder.Make(typeof(Member), "FirstName", FilterOperator.IsEqualTo, q.FirstName));

var newExpr = PredicateBuilder.And(expressions.ToArray());

var query = PredicateBuilder.FilterQuery(entityManager.Members, newExpr);

var results = query.Execute<Member>();

results.ForEach(Members.Add);

}



Posted By: BillG
Date Posted: 03-Aug-2010 at 1:23pm
Ok I found the problem it was missing a > in the first line but where is the Expression class located?
 
Bill
 


Posted By: BillG
Date Posted: 03-Aug-2010 at 1:58pm
Make a little bit more progress, Expression is in System.Linq.Expressions. here is the updated code so far
 

public void FetchMembers(MemberQuery q)

{

List<Expression<Func<Member, bool>>> expressions = new List<Expression<Func<Member, bool>>>();

if(q.SSN != string.Empty)

expressions.Add(PredicateBuilder.Make(typeof(Member), "SocSecNo", FilterOperator.IsEqualTo, q.SSN));

if(q.CardNo != 0)

expressions.Add(PredicateBuilder.Make(typeof(Member), "CardNo", FilterOperator.IsEqualTo, q.CardNo));

if(q.EmployeeNo != string.Empty)

expressions.Add(PredicateBuilder.Make(typeof(Member), "EmployeeNo", FilterOperator.IsEqualTo, q.EmployeeNo));

if(q.LastName != string.Empty)

expressions.Add(PredicateBuilder.Make(typeof(Member), "LastName", FilterOperator.IsEqualTo, q.LastName));

if(q.FirstName != string.Empty)

expressions.Add(PredicateBuilder.Make(typeof(Member), "FirstName", FilterOperator.IsEqualTo, q.FirstName));

var newExpr = PredicateBuilder.And(expressions.ToArray());

var query = PredicateBuilder.FilterQuery(entityManager.Members, newExpr);

var results = query.Execute<Member>();

results.ForEach(Members.Add);

}

I am getting two made errors they prefer to each add line.

Error 1 The best overloaded method match for 'System.Collections.Generic.List<System.Linq.Expressions.Expression<System.Func<DomainModel.Member,bool>>>.Add(System.Linq.Expressions.Expression<System.Func<DomainModel.Member,bool>>)' has some invalid arguments D:\Software Development\VS2010\TicketWare2010\TicketWare2010\Models\MemberViewModel.cs 67 18 TicketWare2010
Error 2 Argument 1: cannot convert from 'IdeaBlade.Linq.PredicateDescription' to 'System.Linq.Expressions.Expression<System.Func<DomainModel.Member,bool>>' D:\Software Development\VS2010\TicketWare2010\TicketWare2010\Models\MemberViewModel.cs 67 34 TicketWare2010


Posted By: BillG
Date Posted: 04-Aug-2010 at 3:09pm
Any ideas?



Posted By: GregD
Date Posted: 24-Aug-2010 at 6:00pm
Bill:

Thanks for backchannelling  the AdventureworksDB-backed sample. That made it a lot easier to understand and address your question. 

Here's a version of your FetchCustomers() method that compiles:

    public void FetchCustomers(CustomerQueryObject q) {
      List<PredicateDescription> predicateDescriptions = new List<PredicateDescription>();

      PredicateDescription aPredicateDescription;
      if (q.CompanyName != string.Empty) {
        aPredicateDescription = PredicateBuilder.Make(typeof(Customer), "CompanyName", FilterOperator.IsEqualTo, q.CompanyName);
        predicateDescriptions.Add(aPredicateDescription);
      }

      if (q.LastName != string.Empty)
        predicateDescriptions.Add(PredicateBuilder.Make(typeof(Customer), "LastName", FilterOperator.IsEqualTo, q.LastName));

      if (q.FirstName != string.Empty)
        predicateDescriptions.Add(PredicateBuilder.Make(typeof(Customer), "FirstName", FilterOperator.IsEqualTo, q.FirstName));

      CompositePredicateDescription aCompositePredicateDescription = PredicateBuilder.And(predicateDescriptions.ToArray());
      IQueryable query = PredicateBuilder.FilterQuery(mgr.Customers, aCompositePredicateDescription);

      IEnumerable results = mgr.ExecuteQuery((IEntityQuery)query);

      foreach (Customer aCustomer in results) {
        Customers.Add(aCustomer);
      }

    }



Print Page | Close Window