views:

433

answers:

4

In another posting: Does Linq-To-Sql support composable queries there was discussion on how to compose/concat where clauses dynamically. This appears to be done with an "AND" (i.e. the first where clause and the second where clause are joined by an AND). What I am wondering is if there is a way to compose Linq queries with an OR.

Example:

var people = from p in Person
             where p.age < 18
             select p

var otherPeople = from p in people
                  where p.firstName equals "Daniel"
                  select p

This gives people with a first name of "Daniel" and that are under 18. I'm looking for the syntax to join these to find people who have a first name of "Daniel" or are under 18.

Note: I am using ADO.net Data Services so I do not have .Contains() available to me.

EDIT: The Union Suggestion (by Garry Shutler) is exactly what I am looking for funtionality-wise. I did run into two possible issues with it:

  1. It looks like it would make multiple database hits if I was to do a third condition (union seems to take an IEnumerable as its parameter) - I was hoping to build up multiple AND and OR statements in code and then execute one request.
  2. Union is not supported by ADO.Net Data Services (very disappointing)
+5  A: 

Is what you want as simple as:

var people = from p in Person
             where p.age < 18 || p.firstName == "Daniel"
             select p;

or have you just given a simple example?

In which case you can use:

var under18 = from p in Person
              where p.age < 18
              select p;

var daniels = from p in Person
              where p.firstName == "Daniel"
              select p;

var combined = under18.Union(daniels);

LinqToSql may be intelligent enough to convert that to an OR but I'm not so sure.

Garry Shutler
+1  A: 

What about using PredicateBuilder by Joe Albahari?

var predicate = PredicateBuilder.False<Person>();
predicate = predicate.Or(p => p.age < 18);
predicate = predicate.Or(p => p.firstName == "Daniel");

var query = Person.Where(predicate);
Cameron MacFarland
Predicate Builder doesn't appear to support ADO.Net Data Services? Doing the above results in: "Error translating Linq expression to URI: The expression ((False Or Invoke(m => m.FirstName = "Daniel"),[10007])) Or Invoke(p => (p.age < 18),[10007])) is not supported."
ChrisHDog
Actually this means the fault is in Linq to ADO.NET Data Services as it doesn't support or expressions.
Cameron MacFarland
A: 

The predicate option is the way to go. The Union option DOES NOT build good sql. Reference http://social.msdn.microsoft.com/forums/en-US/linqprojectgeneral/thread/925b245d-5529-4a64-8cd4-4bc83ee6fe7a/

zainnab
It looks like Linq to ADO.Net Data Services doesn't support expressions/predicate builder (see comments on Cameron MacFarland's post for details), so this wouldn't work for this situation - might just have to wait for Linq to ADO.Net Data Services to support that functionality.
ChrisHDog
+1  A: 

Hi Chris,
I wrote about how to achieve queries which search for a key value within a set on my blog . Here are the relevant links.

Contains Operations in ADO.NET Data Services Part I

Contains Operations in ADO.NET Data Services Part II

Using this , you can write queries which look like this
//The set in which we have to search for a match
List<string> citiesIWillVisit = new List<string>() {"London","Berlin","Prague"};
var customersAround = nwContext.Customers
.IsIn<Customers>(citiesIWillVisit, c=> c.City);
foreach (Customers localCustomer in customersAround) {
System.Console.WriteLine(localCustomer.ContactName);
}

Phani Raj