为orderby语句添加通用排序器表达式

时间:2014-03-06 14:30:45

标签: c# .net linq entity-framework

(我已将所有代码简化为仅具有特定问题)

我创建了一些不同的服务方法,它们接受一个排序表达式,我想在一个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));

如果我只传入某些类型,第一种方法可以正常工作。如果我传入DateTimeNullable类型,则会抛出异常,表示无法将这些类型转换为object

如果我传入一个排序表达式,第二种方法可以正常工作。但是,如果我尝试传入一个集合(或params),我能够工作的唯一方法基本上是最后一个排序顺序覆盖前一个。

我如何更改其中一个以便它采用多个排序表达式,它处理OrderByThenBy,它适用于所有类型?

1 个答案:

答案 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();
}