Dynamically building Predicate description
Author
Share Topic Topic Search Topic Options
BillG
DevForce MVP
Joined: 05-Dec-2007
Location: Monroe, MI
Posts: 233
Post Options
Quote Reply
Topic: Dynamically building Predicate description 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
GregD
IdeaBlade
Joined: 09-May-2007
Posts: 374
Post Options
Quote Reply
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);
BillG
DevForce MVP
Joined: 05-Dec-2007
Location: Monroe, MI
Posts: 233
Post Options
Quote Reply
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);
}
BillG
DevForce MVP
Joined: 05-Dec-2007
Location: Monroe, MI
Posts: 233
Post Options
Quote Reply
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
BillG
DevForce MVP
Joined: 05-Dec-2007
Location: Monroe, MI
Posts: 233
Post Options
Quote Reply
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
BillG
DevForce MVP
Joined: 05-Dec-2007
Location: Monroe, MI
Posts: 233
Post Options
Quote Reply
Posted: 04-Aug-2010 at 3:09pm
Any ideas?
GregD
IdeaBlade
Joined: 09-May-2007
Posts: 374
Post Options
Quote Reply
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);
}
}
Forum Jump
-- Select Forum --
Community Forum
Community Forum
Community Forum now on StackOverflow
DevForce 2012
DevForce 2010
DevForce 2009
DevForce Classic
Forum Permissions You cannot post new topics in this forum You cannot reply to topics in this forum You cannot delete your posts in this forum You cannot edit your posts in this forum You cannot create polls in this forum You cannot vote in polls in this forum