I am creating a query to return some data from a database. I am passing in a list of ids that I want to filter on. If the filter list is null or empty I want to return all the things.
I have an extension method that lets me do this query
is an IQueryable
, Ids
is a list of nullable ints (don't ask!) ListHasElements
is a method that returns true if the list is non-null and has something in it.
var filteredList = query.WhereIf(ListHasElements(Ids), s => Ids.Contains(s.Id.Value));
However when I build query
I use my prefered query syntax
var query = from a in dbContext.as
join b in dbContext.bs on a.Id.ToString() equals b.Id
join cin dbContext.cs on b.Id equals c.Id into bcJoin
from items in bcJoin.DefaultIfEmpty()
where b.Sent >= fromDate
where b.Sent <= toDate
select new{a=a.thing, b=b.thingy, q=items.q,Id=a.Id}
Then I have to insert the initial line to do my magic WhereIf filter. and finally a further select to group by and create my output object (code not shown!)
The extension method looks like this.
public static IQueryable<TSource> WhereIf<TSource>(this IQueryable<TSource> source, bool condition,
Expression<Func<TSource, bool>> predicate)
{
return condition ? source.Where(predicate) : source;
}
Can I use this method directly in my query syntax query?
Quote from MSDN :
Some queries must be expressed as method calls
This is one of those cases. Even some of their own extension methods must be called via method syntax. For example, Count
.
You can't. The compiler takes well-known query syntax keywords and converts them to method syntax behind-the-scenes. It knows nothing of your custom extension and thus has no equivalent in query syntax. Note that other "built-in" linq functions have no query syntax equivalent:
Skip
Count
Take
Single
FirstOrDefault
Max
Although I would note that your extension is basically equivalent to
where !condition || predicate(b)
YES!
var query = from a in dbContext.as.WhereIf(ListHasElements(Ids), s => Ids.Contains(s.Id.Value))
join b in dbContext.bs on a.Id.ToString() equals b.Id
join cin dbContext.cs on b.Id equals c.Id into bcJoin
from items in bcJoin.DefaultIfEmpty()
where b.Sent >= fromDate
where b.Sent <= toDate
select new{a=a.thing, b=b.thingy, q=items.q,Id=a.Id}
My test code (Listings is a table with an Id field):
void Main()
{
var list=new int []{1,2,3,4};
var query=from l in Listings.WhereIf(ListHasElements(list),s=>list.Contains(s.Id))
select l;
query.Dump();
}
public bool ListHasElements<T>(IEnumerable<T> it)
{
return it.Any();
}
public static class Ext {
public static IQueryable<TSource> WhereIf<TSource>(this IQueryable<TSource> source, bool condition,
Expression<Func<TSource, bool>> predicate)
{
return condition ? source.Where(predicate) : source;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.