使用Entity Framework 6,我正在寻找相当于Aggregate
- 带有种子的重载 - 但是从种子延伸而不是从聚合集合延伸。也就是说,给定Expression<Func<T, bool>>
的集合(适用于Where
),我想将它们连续应用于基础IQueryable
。
注意:即使Linq to Entities本身不支持Aggregate
,但诀窍是我们不会尝试将Aggregate
操作投射到SQL中,我们正在使用{{1}方法IEnumerable
将条件添加到Aggregate
。因此,只要IQueryable
是种子,Aggregate
就可以与EF一起使用,而不是扩展方法的IQueryable
参数。
所以给出了这个设置:
this
而不是:
public class Product {
public int Name { get; set; }
public int Size { get; set; }
public int Price { get; set; }
}
var products = new List<Product> {
new Product { Name = "toaster", Size = 100, Price = 49 },
new Product { Name = "pencil", Size = 2, Price = 5 },
new Product { Name = "Oven", Size = 500, Price = 1000 }
}.AsEnumerable(); // please pretend this is an `IQueryable`
var conditions = new List<Func<Product, bool>> {
{ o => o.Size > 50 },
{ o => o.Price < 100 }
}.AsEnumerable(); // please pretend this is of Expression<Func<Product, bool>>
我想改为能够使用:
IQueryable<Product> filtered =
conditions.Aggregate(queryable, (current, condition) => current.Where(condition));
这是我必须编写自己的扩展方法,还是有办法用本机Linq to Entities扩展方法实现这一点?我认为IQueryable<Product> filtered = queryable.WhereAll(conditions);
语法在没有发生真正聚合的情况下会令人困惑(至少,开发人员会如何思考)。如果我确实使用Aggregate
,我认为在代码中会出现令人惊讶或混乱,首先是因为没有真正的聚合发生(例如求和或连接),其次是因为当Aggregate
是一个空集合时,它仍然返回种子(使用可查询/集合和扩展方法的一些非惯用和令人惊讶的结果,其中返回值不是扩展方法操作的对象的转换)。
我愿意接受比conditions
更好的名字。我考虑过WhereAll
,Transform
和Map
。
如果仅适用于Apply
和Linq to Objects,the answer is easy:
IEnumerables
但是,对于Linq to Entities,无法将其投影到SQL中,因为您无法手动处理lambda中的表达式以将表达式正确添加到父表达式树中(表达式本身必须是整个lambda),除非你想对products.Where(p => conditions.All(c => c(p)));
的表达式进行复杂的手术(对此过度杀伤)。
答案 0 :(得分:0)
编写扩展方法很简单..
public static IQueryable<T> WhereAll<T>(this IQueryable<T> q,IEnumerable<Expression<Func<T, bool>>> conditions)
{
foreach(var condition in conditions)
q=q.Where(condition);
return q;
}
您也可以使用PredicateBuilder。在所有条件下初始化为True和AND
,然后只使用常规.Where
和您构建的复合谓词。