Linq orderbys из коллекции [duplicate]

$username = $_POST['username'];
$password = $_POST['password'];
$result = mysql_query("SELECT * FROM Users WHERE UserName LIKE '%$username%'") or die(mysql_error());

while($row = mysql_fetch_array($result))
{
    echo $row['FirstName'];
}

Иногда подавление запроса как @mysql_query(your query);

64
задан John Demetriou 21 December 2015 в 11:27
поделиться

10 ответов

Есть возможность использования отражения ...

var param = "Address";    
var propertyInfo = typeof(Student).GetProperty(param);    
var orderByAddress = items.OrderBy(x => propertyInfo.GetValue(x, null));
102
ответ дан codeConcussion 31 August 2018 в 18:48
поделиться

Вот что я придумал для того, чтобы иметь дело с условным Descending. Вы можете комбинировать это с другими методами генерации динамической функции keySelector.

    public static IOrderedQueryable<TSource> OrderBy<TSource, TKey>(this IQueryable<TSource> source,
            System.Linq.Expressions.Expression<Func<TSource, TKey>> keySelector,
            System.ComponentModel.ListSortDirection sortOrder
            )
    {
        if (sortOrder == System.ComponentModel.ListSortDirection.Ascending)
            return source.OrderBy(keySelector);
        else
            return source.OrderByDescending(keySelector);
    }

Использование:

//imagine this is some parameter
var direction = System.ComponentModel.ListSortDirection.Ascending;
query = query.OrderBy(ec => ec.MyColumnName, direction);

Обратите внимание, что это позволяет вам связать это расширение .OrderBy с новый параметр на любой IQueryable.

// perhaps passed in as a request of user to change sort order
// var direction = System.ComponentModel.ListSortDirection.Ascending;
query = context.Orders
        .Where(o => o.Status == OrderStatus.Paid)
        .OrderBy(ec => ec.OrderPaidUtc, direction);
4
ответ дан AaronLS 31 August 2018 в 18:48
поделиться

Вы можете использовать немного рефлекса для построения дерева выражений следующим образом (это метод расширения):

public static IQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string orderByProperty,
                          bool desc) 
{
     string command = desc ? "OrderByDescending" : "OrderBy";
     var type = typeof(TEntity);
     var property = type.GetProperty(orderByProperty);
     var parameter = Expression.Parameter(type, "p");
     var propertyAccess = Expression.MakeMemberAccess(parameter, property);
     var orderByExpression = Expression.Lambda(propertyAccess, parameter);
     var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType },
                                   source.Expression, Expression.Quote(orderByExpression));
     return source.Provider.CreateQuery<TEntity>(resultExpression);
}

orderByProperty - это имя свойства, которое вы хотите заказать, и если передать true как параметр для desc, будет сортироваться в порядке убывания; в противном случае будет сортироваться в порядке возрастания.

Теперь вы должны иметь возможность делать existingStudents.OrderBy("City",true); или existingStudents.OrderBy("City",false);

78
ответ дан Icarus 31 August 2018 в 18:48
поделиться

1) Установите System.Linq.Dynamic

2) Добавьте следующий код

public static class OrderUtils
{
    public static string ToStringForOrdering<T, TKey>(this Expression<Func<T, TKey>> expression, bool isDesc = false)
    {
        var str = expression.Body.ToString();
        var param = expression.Parameters.First().Name;
        str = str.Replace("Convert(", "(").Replace(param + ".", "");
        return str + (isDesc ? " descending" : "");
    }
}

3) Напишите свой переключатель для выбора Lambda function

public static class SortHelper
{
    public static Expression<Func<UserApp, object>> UserApp(string orderProperty)
    {
        orderProperty = orderProperty?.ToLowerInvariant();
        switch (orderProperty)
        {
            case "firstname":
                return x => x.PersonalInfo.FirstName;
            case "lastname":
                return x => x.PersonalInfo.LastName;
            case "fullname":
                return x => x.PersonalInfo.FirstName + x.PersonalInfo.LastName;
            case "email":
                return x => x.Email;

        }
    }
}

4) Используйте ваши помощники

Dbset.OrderBy(SortHelper.UserApp("firstname").ToStringForOrdering())

5) Вы можете использовать его с pagging ( PagedList )

public virtual  IPagedList<T> GetPage<TOrder>(Page page, Expression<Func<T, bool>> where, Expression<Func<T, TOrder>> order, bool isDesc = false,
      params Expression<Func<T, object>>[] includes)
    {
        var orderedQueryable = Dbset.OrderBy(order.ToStringForOrdering(isDesc));
        var query = orderedQueryable.Where(where).GetPage(page);
        query = AppendIncludes(query, includes);

        var results = query.ToList();
        var total =  Dbset.Count(where);

        return new StaticPagedList<T>(results, page.PageNumber, page.PageSize, total);
    }

Объяснение

System.Linq.Dynamic позволяет нам установить строковое значение в методе OrderBy. Но внутри этого расширения строка будет анализироваться на Lambda. Поэтому я подумал, что это сработает, если мы проанализируем Lambda на строку и передадим ее методу OrderBy. И это работает!

4
ответ дан Igor Valikovsky 31 August 2018 в 18:48
поделиться

Это не позволяет вам передать string, как вы просили в своем вопросе, но он все равно может работать для вас.

Метод OrderByDescending принимает Func<TSource, TKey>, поэтому вы можете переписать свою функцию следующим образом:

List<Student> QueryStudents<TKey>(Func<Student, TKey> orderBy)
{
    return existingStudents.OrderByDescending(orderBy).ToList();
}

Существуют и другие перегрузки для OrderByDescending, которые берут Expression<Func<TSource, TKey>> и / или IComparer<TKey>. Вы также можете посмотреть на них и посмотреть, предоставляют ли они вам что-нибудь полезное.

1
ответ дан Merlyn Morgan-Graham 31 August 2018 в 18:48
поделиться

Чтобы расширить ответ на @Icarus : если вы хотите, чтобы возвращаемый тип метода расширения был IOrderedQueryable вместо IQueryable, вы можете просто сделать результат следующим образом:

public static IOrderedQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string orderByProperty, bool desc)
{
    string command = desc ? "OrderByDescending" : "OrderBy";
    var type = typeof(TEntity);
    var property = type.GetProperty(orderByProperty);
    var parameter = Expression.Parameter(type, "p");
    var propertyAccess = Expression.MakeMemberAccess(parameter, property);
    var orderByExpression = Expression.Lambda(propertyAccess, parameter);
    var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType },
        source.Expression, Expression.Quote(orderByExpression));
    return (IOrderedQueryable<TEntity>)source.Provider.CreateQuery<TEntity>(resultExpression);
}
1
ответ дан Mogsdad 31 August 2018 в 18:48
поделиться

Я опоздал на вечеринку, но ни один из этих решений не работал для меня. Я очень хотел попробовать System.Linq.Dynamic, но я не мог найти это на Nuget, возможно, обесценился? В любом случае ...

Вот решения, которые я придумал. Мне нужно было динамически использовать смесь OrderBy, OrderByDescending и OrderBy> ThenBy.

Я просто создал метод расширения для моего объекта списка, немного взломанный, я знаю ... Я бы не рекомендовал это, если он было что-то, что я делал много, но это хорошо для одного.

List<Employee> Employees = GetAllEmployees();

foreach(Employee oEmployee in Employees.ApplyDynamicSort(eEmployeeSort))
{
    //do stuff
}

public static IOrderedEnumerable<Employee> ApplyDynamicSort(this List<Employee> lEmployees, Enums.EmployeeSort eEmployeeSort)
{
    switch (eEmployeeSort)
    {
        case Enums.EmployeeSort.Name_ASC:
            return lEmployees.OrderBy(x => x.Name);
        case Enums.EmployeeSort.Name_DESC:
            return lEmployees.OrderByDescending(x => x.Name);
        case Enums.EmployeeSort.Department_ASC_Salary_DESC:
            return lEmployees.OrderBy(x => x.Department).ThenByDescending(y => y.Salary);
        default:
            return lEmployees.OrderBy(x => x.Name);
    }
}
-1
ответ дан Nicolay 31 August 2018 в 18:48
поделиться
  • Добавить пакет самородок Dynamite в ваш код
  • Добавить пространство имен Dynamite.Extensions Например: using Dynamite.Extensions;
  • Дать заказ по запросу, как любой SQL-запрос Eg : students.OrderBy («City DESC, Address»). ToList ();
0
ответ дан Sreeja S J 31 August 2018 в 18:48
поделиться

Единственное решение, которое сработало для меня, было опубликовано здесь https://gist.github.com/neoGeneva/1878868 by neoGeneva.

Я повторно опубликую его код потому что он работает хорошо, и я бы не хотел, чтобы он терялся в сетях!

    public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string sortExpression)
    {
        if (source == null)
            throw new ArgumentNullException("source", "source is null.");

        if (string.IsNullOrEmpty(sortExpression))
            throw new ArgumentException("sortExpression is null or empty.", "sortExpression");

        var parts = sortExpression.Split(' ');
        var isDescending = false;
        var propertyName = "";
        var tType = typeof(T);

        if (parts.Length > 0 && parts[0] != "")
        {
            propertyName = parts[0];

            if (parts.Length > 1)
            {
                isDescending = parts[1].ToLower().Contains("esc");
            }

            PropertyInfo prop = tType.GetProperty(propertyName);

            if (prop == null)
            {
                throw new ArgumentException(string.Format("No property '{0}' on type '{1}'", propertyName, tType.Name));
            }

            var funcType = typeof(Func<,>)
                .MakeGenericType(tType, prop.PropertyType);

            var lambdaBuilder = typeof(Expression)
                .GetMethods()
                .First(x => x.Name == "Lambda" && x.ContainsGenericParameters && x.GetParameters().Length == 2)
                .MakeGenericMethod(funcType);

            var parameter = Expression.Parameter(tType);
            var propExpress = Expression.Property(parameter, prop);

            var sortLambda = lambdaBuilder
                .Invoke(null, new object[] { propExpress, new ParameterExpression[] { parameter } });

            var sorter = typeof(Queryable)
                .GetMethods()
                .FirstOrDefault(x => x.Name == (isDescending ? "OrderByDescending" : "OrderBy") && x.GetParameters().Length == 2)
                .MakeGenericMethod(new[] { tType, prop.PropertyType });

            return (IQueryable<T>)sorter
                .Invoke(null, new object[] { source, sortLambda });
        }

        return source;
    }
1
ответ дан user1477388 31 August 2018 в 18:48
поделиться
   private Func<T, object> GetOrderByExpression<T>(string sortColumn)
    {
        Func<T, object> orderByExpr = null;
        if (!String.IsNullOrEmpty(sortColumn))
        {
            Type sponsorResultType = typeof(T);

            if (sponsorResultType.GetProperties().Any(prop => prop.Name == sortColumn))
            {
                System.Reflection.PropertyInfo pinfo = sponsorResultType.GetProperty(sortColumn);
                orderByExpr = (data => pinfo.GetValue(data, null));
            }
        }
        return orderByExpr;
    }

    public List<T> OrderByDir<T>(IEnumerable<T> source, string dir, Func<T, object> OrderByColumn)
    {
        return dir.ToUpper() == "ASC" ? source.OrderBy(OrderByColumn).ToList() : source.OrderByDescending(OrderByColumn).ToList();``
    }

 // Call the code like below
        var orderByExpression= GetOrderByExpression<SearchResultsType>(sort);

    var data = OrderByDir<SponsorSearchResults>(resultRecords, SortDirectionString, orderByExpression);    
4
ответ дан user3440420 31 August 2018 в 18:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: