如何将任意(可能是复合的)排序序列附加到IQueryable

时间:2014-03-06 17:08:49

标签: c# linq

我希望将一个或多个排序子句的任意序列(通过动态linq使用表达式而不是字符串声明)附加到IQueryable。怎么可能这样做?

这是问题的关键所在:

private IOrderedQueryable<TProject> Demo<TSource, TProject>(
    IQueryable<TSource> query,
    Expression<Func<TSource, TProject>> project,
    Expression<Func<IQueryable<TProject>, IOrderedQueryable<TProject>>> order
) {
    var projection = query.Select(project);
    //??? How to combine project and order as an expression tree
    var orderedProjection = order.Compile()(projection);
    //??? rather than a compiled delegate (as shown here)
    return orderedProjection;
}


更多上下文(由khellang指出不会编译):

private class ProjectOrder<TProjection> {
    public Expression<Func<Part, TProjection>> Projection { get; set; }
    public Expression<Func<IQueryable<TProjection>, IOrderedQueryable<TProjection>>> Ordering { get; set; }
}

private class PartFilters {
    public string Text { get; set; }
    public string[] PartNumbers { get; set; }
    public int[] PartTypes { get; set; }
    //....
}

private IOrderedQueryable<TProjection> Fetch<TProjection>(ProjectOrder<TProjection> projectOrder, PartFilters filters) {
    var baseQuery = _db.Part_Parts;

    //append where predicates to baseQuery based on filters

    var projection = baseQuery.Select(projectOrder.Projection);

    //??? How to combine projection and ordering as
    var orderedProjection = projectOrder.Ordering.Compile()(projection);
    //??? an expression tree rather than a compiled delegate

    return orderedProjection;
}

private void TestFetch(PartFilters filters) {

    Expression<Func<Part, PartDescription>> projection = _ => new PartDescription() {
        PartNumber = _.PartNumber,
        Description = _.Description
    };

    //Arbitrary sorting expression, multiple clauses, could use base classes or joined entities
    //via navigation properties
    Expression<Func<IQueryable<PartDescription>, IOrderedQueryable<PartDescription>>> order =
                        q => q.OrderBy(_ => _.PartNumber.Length).ThenBy(_ => _.PartNumber);

    var projectOrder = new ProjectOrder<PartDescription>() {
        Projection = projection,
        Ordering = order
    };

    Fetch<PartDescription>(projectOrder, filters);
}

1 个答案:

答案 0 :(得分:1)

第三个参数根本没有理由成为表达式。它可以只是一个普通的代表。

这里的重点是执行order实际上并没有执行排序。执行order 操纵查询的表达式。您不需要Expression来表示如何操纵Expression对象。你可以这样做。

private IOrderedQueryable<TProject> Demo<TSource, TProject>(
    IQueryable<TSource> query,
    Expression<Func<TSource, TProject>> projection,
    Func<IQueryable<TProject>, IOrderedQueryable<TProject>> order) 
{
    return order(query.Select(projection));
}

瞧,你有一个方法可以根据投影和排序来构建查询。