如何使用动态字符串参数执行OrderBy?

时间:2010-04-28 09:47:38

标签: linq sql-order-by

我想这样做:

var orderBy = "Nome, Cognome desc";

var timb = time.Timbratures.Include("Anagrafica_Dipendente")
    .Where(p => p.CodDipendente == 1);

if(orderBy != "")
    timb = timb.OrderBy(orderBy);

是否有可用的OrderBy重载接受字符串参数?

9 个答案:

答案 0 :(得分:61)

如果您使用简单的LINQ到对象并且不想依赖外部库,那么实现您想要的并不难。

OrderBy()子句接受Func<TSource, TKey>,它从源元素获取排序键。您可以在OrderBy()子句之外定义函数:

Func<Item, Object> orderByFunc = null;

然后,您可以根据排序条件将其分配给不同的值:

if (sortOrder == SortOrder.SortByName)
  orderByFunc = item => item.Name;
else if (sortOrder == SortOrder.SortByRank)
  orderByFunc = item => item.Rank;

然后你可以排序:

var sortedItems = items.OrderBy(orderByFunc);

此示例假定源类型为Item,其属性为NameRank

请注意,在此示例中TKeyObject,不约束可以排序的属性类型。如果func返回一个值类型(如Int32),它将在排序时被装箱,这有点效率低下。如果您可以将TKey限制为特定值类型,则可以解决此问题。

答案 1 :(得分:40)

绝对。您可以使用找到on Scott Guthrie's blog的LINQ动态查询库。还有一个更新版本on CodePlex

它允许您通过传入字符串参数来创建OrderBy子句,Where子句以及其他所有子句。它非常适合创建用于排序/过滤网格的通用代码等。

var result = data
    .Where(/* ... */)
    .Select(/* ... */)
    .OrderBy("Foo asc");

var query = DbContext.Data
    .Where(/* ... */)
    .Select(/* ... */)
    .OrderBy("Foo ascending");

答案 2 :(得分:29)

codeConcussion(https://stackoverflow.com/a/7265394/2793768

的另一个解决方案
var param = "Address";    
var pi = typeof(Student).GetProperty(param);    
var orderByAddress = items.OrderBy(x => pi.GetValue(x, null));

答案 3 :(得分:13)

您不需要外部库。以下代码适用于LINQ to SQL /实体。

Intent.FLAG_ACTIVITY_CLEAR_TOP

(从https://stackoverflow.com/a/16208620/111438复制 /// <summary> /// Sorts the elements of a sequence according to a key and the sort order. /// </summary> /// <typeparam name="TSource">The type of the elements of <paramref name="query" />.</typeparam> /// <param name="query">A sequence of values to order.</param> /// <param name="key">Name of the property of <see cref="TSource"/> by which to sort the elements.</param> /// <param name="ascending">True for ascending order, false for descending order.</param> /// <returns>An <see cref="T:System.Linq.IOrderedQueryable`1" /> whose elements are sorted according to a key and sort order.</returns> public static IQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> query, string key, bool ascending = true) { if (string.IsNullOrWhiteSpace(key)) { return query; } var lambda = (dynamic)CreateExpression(typeof(TSource), key); return ascending ? Queryable.OrderBy(query, lambda) : Queryable.OrderByDescending(query, lambda); } private static LambdaExpression CreateExpression(Type type, string propertyName) { var param = Expression.Parameter(type, "x"); Expression body = param; foreach (var member in propertyName.Split('.')) { body = Expression.PropertyOrField(body, member); } return Expression.Lambda(body, param); }

答案 4 :(得分:9)

最简单的&amp;最好的解决方案:

mylist.OrderBy(s => s.GetType().GetProperty("PropertyName").GetValue(s));

答案 5 :(得分:6)

查看此博客here。它通过定义EntitySorter<T>来描述一种方法。

它允许您将IEntitySorter<T>传入您的服务方法并使用它:

public static Person[] GetAllPersons(IEntitySorter<Person> sorter)
{
    using (var db = ContextFactory.CreateContext())
    {
        IOrderedQueryable<Person> sortedList = sorter.Sort(db.Persons);

        return sortedList.ToArray();
    }
}

你可以像这样创建一个EntitiySorter

IEntitySorter<Person> sorter = EntitySorter<Person>
    .OrderBy(p => p.Name)
    .ThenByDescending(p => p.Id);

或者像这样:

var sorter = EntitySorter<Person>
     .OrderByDescending("Address.City")
     .ThenBy("Id");

答案 6 :(得分:6)

我这样做了:

using System.Linq.Expressions;

namespace System.Linq
{
    public static class LinqExtensions
    {

        public static IOrderedQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> source, string field, string dir = "asc")
        {
            // parametro => expressão
            var parametro = Expression.Parameter(typeof(TSource), "r");
            var expressao = Expression.Property(parametro, field);
            var lambda = Expression.Lambda(expressao, parametro); // r => r.AlgumaCoisa
            var tipo = typeof(TSource).GetProperty(field).PropertyType;

            var nome = "OrderBy";
            if (string.Equals(dir, "desc", StringComparison.InvariantCultureIgnoreCase))
            {
                nome = "OrderByDescending";
            }
            var metodo = typeof(Queryable).GetMethods().First(m => m.Name == nome && m.GetParameters().Length == 2);
            var metodoGenerico = metodo.MakeGenericMethod(new[] { typeof(TSource), tipo });
            return metodoGenerico.Invoke(source, new object[] { source, lambda }) as IOrderedQueryable<TSource>;

        }

        public static IOrderedQueryable<TSource> ThenBy<TSource>(this IOrderedQueryable<TSource> source, string field, string dir = "asc")
        {
            var parametro = Expression.Parameter(typeof(TSource), "r");
            var expressao = Expression.Property(parametro, field);
            var lambda = Expression.Lambda<Func<TSource, string>>(expressao, parametro); // r => r.AlgumaCoisa
            var tipo = typeof(TSource).GetProperty(field).PropertyType;

            var nome = "ThenBy";
            if (string.Equals(dir, "desc", StringComparison.InvariantCultureIgnoreCase))
            {
                nome = "ThenByDescending";
            }

            var metodo = typeof(Queryable).GetMethods().First(m => m.Name == nome && m.GetParameters().Length == 2);
            var metodoGenerico = metodo.MakeGenericMethod(new[] { typeof(TSource), tipo });
            return metodoGenerico.Invoke(source, new object[] { source, lambda }) as IOrderedQueryable<TSource>;
        }

    }
}

使用:

example.OrderBy("Nome", "desc").ThenBy("other")

工作如下:

example.OrderByDescending(r => r.Nome).ThenBy(r => r.other)

答案 7 :(得分:4)

您需要使用LINQ Dynamic查询库以便在运行时传递参数

这将允许像

这样的linq语句
string orderedBy = "Description";
var query = (from p in products
            orderby(orderedBy)
            select p);

答案 8 :(得分:-2)

在上面的一个答案中:

最简单的&amp;最好的解决方案:

mylist.OrderBy(s => s.GetType().GetProperty("PropertyName").GetValue(s));

语法错误,必须添加,null

mylist.OrderBy(s => s.GetType().GetProperty("PropertyName").GetValue(s,null));