You do not have to do this using dynamic query syntax, but you can.
You really have two queries taking place, so you should probably build them as such. You could do it all at once, but you are going to need two specific where clauses in different places either way, one for Genres and one for Titles. Consider the following example that mimics your situation.
class Foo
{
public int Id { get; set; }
public string Name { get; set; }
public List<Bar> Bars { get; set; }
}
class Bar
{
public string Color { get; set; }
}
...
List<Foo> foos = new List<Foo>()
{
new Foo() { Id = 1, Name = "Apple", Bars = new List<Bar> () { new Bar() { Color = "Red"}, new Bar() { Color="Green"}} },
new Foo() { Id = 2, Name = "Orange", Bars = new List<Bar> () { new Bar() { Color = "Orange"},new Bar() { Color="Red Orange"}} },
new Foo() { Id = 3, Name = "Banana",Bars = new List<Bar> () { new Bar() { Color = "Yellow"},new Bar() { Color="Green"}} },
new Foo() { Id = 4, Name = "Pear",Bars = new List<Bar> () { new Bar() { Color = "Green"},new Bar() { Color="Yellow"}} }
};
string fooName = "Apple";
string barColor = "Green";
var fooQuery = foos.AsQueryable();
if (!string.IsNullOrEmpty(fooName))
{
string filter = string.Format("Name = \"{0}\"", fooName);
fooQuery = fooQuery.Where(filter);
}
var barQuery = fooQuery.SelectMany(f => f.Bars);
if (!string.IsNullOrEmpty(barColor))
{
string filter = string.Format("Color = \"{0}\"", barColor);
barQuery = barQuery.Where(filter);
}
The first thing is that it builds a query for Foos. If it requires filtering (based upon the fooSearchName variable), it generates a Where clause and adds it to the query. Afterwards, it becomes the base for the query that returns Bar elements. Same thing, if it requires filtering, a Where clause is generated and added to the query.
Unfortunately, you can't build a single query over steps because of type inference being evaluated on the first step. If you were to say var query = foos.AsQueryable();
, the query has already been evaluated to IQueryable<Foo>
, so adding a SelectMany in a later statement to select Bars fails because that requires that query be an IQueryable<Bar>
.
In that vein, your hand is forced and you must either build the query all at once, or at least to the portion up to and including SelectMany, the final Where clause can be appended later. So you could do this:
var query = foos.AsQueryable().Where(fooSearchClause).SelectMany(f => f.Bars);
// later
query = query.Where(barSearchClause);
Or you build the query as one that uses another, as my example shows.
At any rate, with the terms I've provided, iterating over final query yields one result. Altering the contents of either search variable will cause the query to yield different results.