简体   繁体   中英

How can I use this extension method in a linq to entities query using query syntax?

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
  • etc.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM