OrderBy Lambda的通用列表

我正在尝试构建一个通用的查询机制来访问我的存储库。 我希望使用Lambda表达式来过滤和排序查询。 我正在努力寻找一种方法来传递一般的Lambda表达式列表,特别是对于order-by,并且非常感谢这样做的帮助。

编辑:我想要满足的2个要求是,不要将IQueryable暴露在存储库之外,但仍然能够在数据库级别执行一些过滤和排序。

为了更好地说明这一点,让我向您展示代码

public class Query { public class OrderBy { public Expression<Func> Clause { set; get; } // Order By clause public bool Descending = true; } public Expression<Func> Where { set; get; } // Where clause public IList<OrderBy> OrderBys { set; get; } // Where clause public Query() { OrderBys = new List<OrderBy>(); } } public IEnumerable FindBy(Query query) { IQueryable Temp = GetObjectSet(); if (query.Where != null) Temp = Temp.Where(query.Where); foreach (var OrderByThis in query.OrderBys) { if (OrderByThis.Descending) Temp = Temp.OrderByDescending(OrderByThis.Clause); else Temp = Temp.OrderBy(OrderByThis.Clause); } return Temp.ToList(); } 

这一切都非常好,但Expression <Func <T, int >>不是通用的。 我需要能够做到这样的事情:

 Query query = new Query(); Query.OrderBy clause1 = new Query.OrderBy(); clause1.Clause = m => m.Username; Query.OrderBy clause2 = new Query.OrderBy(); clause2.Clause = m => m.DateOfBirth; query.OrderBys.Add(clause1); query.OrderBys.Add(clause2); 

即添加许多不同类型的不同字段。

我想必须有一种方法将这些存储为通用Lambda函数,然后在存储库中转换为它需要的强类型Lambda函数。

我怎样才能做到这一点?

正如我在回答你的另一个问题时所指出的那样,我总是不鼓励这种做法。 公开IQueryable / IOrderedQueryable更有意义。

话虽如此,在如何将多个表达式传递给OrderBy for EF的选定答案中,有一个解决方案符合您的意图。 。

它允许您使用如下语法:

 var query = context.Users ... ; var queryWithOrderBy = ApplyOrderBy(query, new OrderByExpression(expression: u => u.UserName, descending: false), // a string, asc new OrderByExpression(expression: u => u.UserId, descending: true)); // an int, desc var result = queryWithOrderBy.ToList(); // didn't throw an exception for me 

详细说明我的评论,我不明白为什么你需要从表达式构建自己的中间查询对象,然后从那个中间对象重建表达式,当你可以完全跳过该翻译。

给出您的示例查询:

 repository.FindBy(people => people.OrderBy(p => p.Username).ThenBy(p => p.DateOfBirth)); 

请注意,例如,如果基于用户选择完成查询,您仍然可以逐步构建查询。 以下查询等同于以上内容:

 Func, IEnumerable> query = people => people.OrderBy(p => p.Username); query = query.ThenBy(p => p.DateOfBirth); 

我知道您不希望将IQueryable暴露在存储库之外,但您仍然可以使用带有签名的LINQ,例如:

 public IEnumerable FindBy(Func, IEnumerable> query) { return query(GetObjectSet()).ToList(); } 

但是,根据您的实际问题,您可以通过对Clause属性类型使用Expression>来实现OrderBy任务,或者如果这让您感到不安,则可以通过使用IComparable而不是object来限制它,因为它实际上是您需要的所有订购,字符串和数字类型都实现它。