(我已将所有代码简化为仅具有特定问题)
我创建了一些不同的服务方法,它们接受一个排序表达式,我想在一个order by语句中使用它。
2个版本如下:
public List<Order> GetOrders(Expression<Func<Order, object>> sortExpression)
{
// get the query for the orders table
IQueryable<Order> query = GetQuery();
// order by based on the passed in expression
query = query.OrderBy(sortExpression);
// now execute the query and return the collection
return query.ToList();
}
public List<Order> GetOrders2(Func<IQueryable<Order>, IOrderedQueryable<Order>> orderby)
{
IQueryable<Order> dbQuery = GetQuery();
if (orderby != null)
{
dbQuery = orderby(dbQuery);
}
return dbQuery.ToList();
}
我打电话给他们:
GetOrders(o => o.CreatedOnDate);
GetOrders2(queryable => queryable.OrderBy(o => o.CreatedOnDate));
如果我只传入某些类型,第一种方法可以正常工作。如果我传入DateTime
或Nullable
类型,则会抛出异常,表示无法将这些类型转换为object
。
如果我传入一个排序表达式,第二种方法可以正常工作。但是,如果我尝试传入一个集合(或params),我能够工作的唯一方法基本上是最后一个排序顺序覆盖前一个。
我如何更改其中一个以便它采用多个排序表达式,它处理OrderBy
和ThenBy
,它适用于所有类型?
答案 0 :(得分:1)
首先,如果你想只为GetOrders
提供一个lambda,那么你需要接受一个Expression<Func<Order, object>>
而不是你所拥有的。
要接受任意数量的选择器,最方便的(对于调用者)是在这样的参数上使用params
。
此时,只需在第一个选择器上进行排序,然后在所有后续选择器上调用ThenBy
。
public List<Order> GetOrders(params Expression<Func<Order, object>>[] selectors)
{
var dbQuery = GetQuery();
if (selectors.Any())
{
var orderedQuery = dbQuery.OrderBy(selectors.First());
foreach (var selector in selectors.Skip(1))
orderedQuery = orderedQuery.ThenBy(selector);
dbQuery = orderedQuery;
}
return dbQuery.ToList();
}