Suppose you needed an ad-hoc search interface for the following class:
public class Customer
{public string Id { get; set; }
public string AccountName { get; set; }
public string AccountNumber { get; set; }
public string StateCode { get; set; }
}
The users just want to type something that would be used as criteria against multiple fields, such as a list of words. By itself, that may be simple enough. You decide which properties to query against, split the list of words, and create multiple Where statements
IQueryable<Customer>
query = from c in
Customers
select c;
foreach (string criterion in criteria.Split(' '))
{query = query.Where(c =>
c.AccountName.Contains(criterion) ||
c.AccountNumber.Contains(criterion) ||
c.StateCode.Contains(criterion));
}
return query.ToList();
IQueryable<Customer>
query = from c in
Customers
select c;
Expression<Func<Customer, bool>>
searchclause;
foreach (string criterion in criteria.Split(' '))
{
Expression<Func<Customer,
bool>> predicate = c =>
c.AccountName.Contains(criterion) ||
c.AccountNumber.Contains(criterion) ||
c.StateCode.Contains(criterion));
searchclause
= (searchclause==null) ? predicate :
searchclause.Or(predicate);
}
query = query.Where(searchclause);
return query.AsExpandable().ToList();
IQueryable<Customer>
query = from c in
Customers
select c;
Expression<Func<Customer, bool>>
searchclause = null;
bool useOrCondition = true;
bool useNotCondition = false;
foreach (string criterion in criteria.Split(' '))
{string term = criterion;
if (term.Trim().Length == 0)
{
// do nothing
}
else if (term.ToUpper() == "AND")
{
useOrCondition = false;
}
else if (term.ToUpper() == "OR")
{
useOrCondition = true;
}
else if (term.ToUpper() == "NOT")
{
useNotCondition = true;
useOrCondition = false;
}
else
{
Expression<Func<Customer, bool>> predicateexpression;
if (useOrCondition)
{
predicateexpression = c =>
c.AccountNumber.Contains(term) ||
c.AccountName.Contains(term) ||
c.StateCode.Contains(term);
searchclause = (searchclause == null)
? predicateexpression : searchclause.Or(predicateexpression);
}
else if (useNotCondition)
{
predicateexpression = c =>
c.AccountNumber.Contains(term) &&
c.AccountName.Contains(term) &&
c.StateCode.Contains(term);
searchclause = (searchclause == null)
? predicateexpression : searchclause.And(predicateexpression);
}
else
{
predicateexpression = c =>
c.AccountNumber.Contains(term) ||
c.AccountName.Contains(term) ||
c.StateCode.Contains(term);
searchclause = (searchclause == null)
? predicateexpression : searchclause.And(predicateexpression);
}
useOrCondition = true;
useNotCondition = false;}
}
query = query.Where(searchclause);
return query;
2. It does not handle operator precedence (if you mix AND and OR the results will not likely be what you expect.
3. It does not handle parentheses.
No comments:
Post a Comment