动态排序在LINQ(dynamic sort in linq)

2019-07-31 17:01发布

请考虑以下情况:

我有一个类的大约有50 fields.I名单希望有一个组合框用户可以根据什么字段列表将sort.For例如,如果用户排序按“F1”选择“F1”列表中选择。

我不想用排序if-else为每fields.I看到这个话题:

数据绑定对象的集合或列表排序时,一个gridview

但我不能用它的答案。 如何使用Expression Tree为了这个目的?

谢谢

编辑1):

据亲爱@Thom史密斯回答我写这样的代码:

 using (NorthwindModel1.NorthwindEntities2 ent = new NorthwindModel1.NorthwindEntities2())
    {
        var query = from o in ent.Orders
                    where o.OrderID < 10257
                    select o;

        query.OrderBy("CustomerID", SortDirection.Ascending);

        GridView1.DataSource = query;
        GridView1.DataBind();
    }

但它没有排序。 如果我写的代码是这样的:

GridView1.DataSource = query.OrderBy(o=>o.CustomerID);

它是排序。 问题出在哪儿?

Answer 1:

排序依据不做就地排序。 它返回 评估进行排序的顺序。 这通常是懒洋洋的,意思是:直到它被枚举,它什么都不做 。 您当前的代码简单地丢弃这件十分重要的返回值。 解决方法是简单的:赶返回值:

query = query.OrderBy("CustomerID", SortDirection.Ascending);

注:同样,将“去哪儿”不过滤现有数据:它返回一个序列列举时被过滤。 所以,如果你是过滤你有类似的:

query = query.Where(...);


Answer 2:

下面是我用这个方法:

private IQueryable<T> OrderQuery<T>(IQueryable<T> query, OrderParameter orderBy)
{
    string orderMethodName = orderBy.Direction == SortDirection.Ascending ? "OrderBy" : "OrderByDescending";
    Type t = typeof(T);

    var param = Expression.Parameter(t, "shipment");
    var property = t.GetProperty(orderBy.Attribute);

    /* We can't just call OrderBy[Descending] with an Expression
     * parameter because the second type argument to OrderBy is not
     * known at compile-time.
     */
    return query.Provider.CreateQuery<T>(
        Expression.Call(
            typeof(Queryable),
            orderMethodName,
            new Type[] { t, property.PropertyType },
            query.Expression,
            Expression.Quote(
                Expression.Lambda(
                    Expression.Property(param, property),
                    param))
        ));
}

OrderParameter仅仅是一个与属性和方向结构。

编辑:附加说明。

这种方法是从我DynamicOrderList类,它是名单OrderParameter对象。 如果你需要的是一个字段排序,那么你可以把它简化一下:

private IQueryable<T> OrderByDynamic<T>(this IQueryable<T> query, string attribute, SortDirection direction)
{
    try
    {
        string orderMethodName = direction == SortDirection.Ascending ? "OrderBy" : "OrderByDescending";
        Type t = typeof(T);

        var param = Expression.Parameter(t);
        var property = t.GetProperty(attribute);

        return query.Provider.CreateQuery<T>(
            Expression.Call(
                typeof(Queryable),
                orderMethodName,
                new Type[] { t, property.PropertyType },
                query.Expression,
                Expression.Quote(
                    Expression.Lambda(
                        Expression.Property(param, property),
                        param))
            ));
    }
    catch (Exception) // Probably invalid input, you can catch specifics if you want
    {
        return query; // Return unsorted query
    }
}

然后使用它像:

myQuery = myQuery.OrderByDynamic("name", SortDirection.Ascending);

编辑2:

public IQueryable<T> OrderBy<T>(this IQueryable<T> query, string attribute, SortDirection direction)
{
    return ApplyOrdering(query, attribute, direction, "OrderBy");
}

public IQueryable<T> ThenBy<T>(this IQueryable<T> query, string attribute, SortDirection direction)
{
    return ApplyOrdering(query, attribute, direction, "ThenBy");
}

private IQueryable<T> ApplyOrdering<T>(IQueryable<T> query, string attribute, SortDirection direction, string orderMethodName)
{
    try
    {
        if (direction == SortDirection.Descending) orderMethodName += "Descending";

        Type t = typeof(T);

        var param = Expression.Parameter(t);
        var property = t.GetProperty(attribute);

        return query.Provider.CreateQuery<T>(
            Expression.Call(
                typeof(Queryable),
                orderMethodName,
                new Type[] { t, property.PropertyType },
                query.Expression,
                Expression.Quote(
                    Expression.Lambda(
                        Expression.Property(param, property),
                        param))
            ));
    }
    catch (Exception) // Probably invalid input, you can catch specifics if you want
    {
        return query; // Return unsorted query
    }
}

和:

myQuery=myQuery.OrderBy("name", SortDirection.Ascending).ThenBy("date", SortDirection.Descending);


Answer 3:

看看这个链接使用LINQ场名称的多个字段排序

希望它可以帮助来完成你所需要的。



Answer 4:

这里是我的温热服食,使用Enumerable +反思,而不是查询:

list.OrderBy(x => {
                       var prop = x.GetType().GetProperty(sortFieldName);
                       return prop.GetValue(x);
                   });

if (!isSortAsc) list.Reverse();


Answer 5:

希望这会有所帮助。 它为我工作来过滤C#列表,动态

string jtSorting = "ContactName";
DashboardModel Sup = new DashboardModel();
List<Applicant> lstSup = Sup.GetonBoard();
lstSup = lstSup.AsQueryable().SortBy(jtSorting).ToList();


文章来源: dynamic sort in linq