1

我正在创建一个查询以从数据库中返回一些数据。我正在传递一个我想要过滤的 id 列表。如果过滤器列表为空或为空,我想返回所有内容。

我有一个扩展方法可以让我这样做 ,它query是一个可以为空的整数的列表(不要问!)如果列表为非空并且其中包含某些内容,则该方法返回 true。IQueryableIdsListHasElements

 var filteredList = query.WhereIf(ListHasElements(Ids), s => Ids.Contains(s.Id.Value));

但是,当我构建时,query我使用我喜欢的查询语法

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}

然后我必须插入第一行来做我的魔法 WhereIf 过滤器。最后进一步选择分组并创建我的输出对象(代码未显示!)

扩展方法如下所示。

public static IQueryable<TSource> WhereIf<TSource>(this IQueryable<TSource> source, bool condition,
    Expression<Func<TSource, bool>> predicate)
{
    return condition ? source.Where(predicate) : source;
}

我可以在查询语法查询中直接使用此方法吗?

4

3 回答 3

1

引用MSDN

某些查询必须表示为方法调用

这是其中一种情况。甚至它们自己的一些扩展方法也必须通过方法语法来调用。例如,Count

于 2015-11-03T17:16:39.780 回答
0

你不能。编译器采用众所周知的查询语法关键字并将它们转换为幕后的方法语法。它对您的自定义扩展一无所知,因此在查询语法中没有等效项。请注意,其他“内置” linq 函数没有等效的查询语法:

  • Skip
  • Count
  • Take
  • Single
  • FirstOrDefault
  • Max
  • 等等

虽然我会注意到你的扩展基本上等同于

where !condition || predicate(b)
于 2015-11-03T17:17:54.737 回答
-1

是的!

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}

我的测试代码(Listings 是一个带有 Id 字段的表):

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;
    }
}
于 2015-11-03T18:18:48.400 回答