views:

96

answers:

3

I have a table of product information with many bit columns. This table can be queried from an interface which has a checkbox for each column. The checkboxes are grouped into several related groups.

For example, three of the columns describe the products suitability for various markets, being Automotive, Aviation and Marine.

If none of these checkboxes are checked, I would like the following SQL to be executed.

SELECT * FROM Products

if Automotive was checked the following SQL should be executed

SELECT * FROM Products WHERE Automotive = 1

and if more than one is checked I would like the options to be OR'd together

SELECT * FROM Products WHERE 
    Automotive = 1 
    OR 
    Aviation = 1

In good old C# & SQL I could achieve this logic by conditionally concating the SQL together but I'm having trouble producing the same logic with Linq.

My problem is how do I conditionally add the WHERE clause and the elements of it to my query.

I'd prefer to only have a single point where the query is executed so, if possible, I would like to avoid using C# if's to branch into different queries.

+3  A: 

Having the values be an "Or" vs. an "And" makes this problem a bit more difficult. If it were "And" then the following should do fine

public IEnumerable<Products> GetQuery() {
  var query = db.GetTable<Products>();
  if ( automotiveBox.Checked ) {
    query = query.Where(x => x.Automotive == 1);
  }
  if ( aviation.Checked ) {
    query = query.Where(x => x.Aviation == 1);
  }
  return query
}

With it being an "Or" though I think your only option is to build up the expression tree by hand and use it as a Where clause.

JaredPar
Won't this work for the "Or" case? I believe multiple Where conditions will simply be combined into a single Where clause in the generated SQL. http://stackoverflow.com/questions/1280871/multiple-defered-where-clause-expressions-in-linq-to-sql Seems to back this up.
Chris Shouts
Yes, but they will form an "AND" case in the generated SQL. You're effectively doing where A AND where B AND where C, not where (A OR B OR C), since that requires a different style SQL statement.
Reed Copsey
+3  A: 

If you're trying to "OR" statements together that check a single column, you can use Contains to accomplish this. Here's a good blog post showing how this works.

However, if you're trying to dynamically check different columns, this will not work. In that case, multiple statements will probably be required.

Reed Copsey
+6  A: 

I would use a PredicateBuilder for this.

var query = db.GetTable<Products>().AsQueryable();

var predicate = PredicateBuilder.False<Products>();
if (automotive.Checked)
{
    predicate = predicate.Or( p => p.Automotive == 1 );
}
if (aviation.Checked) 
{
    predicate = predicate.Or( p => p.Aviation == 1 );
}
query = query.Where( predicate );
tvanfosson
+1 for awesomeness
Chris Shouts
Exactly! This PredicateBuilder is slick!!
Greg B