two then orderbydescending multiple columns asc linq

linq - orderbydescending - order by then by c#



¿Cómo puedo usar linq para ordenar por múltiples campos? (6)

Esto funcionará:

YourCollection.Orderby(item => item.Property1).ThenBy(item => item.Property2);

Estoy creando una fuente de datos simulada que quiero poder pasar en una lista de SortExpressions.

public SortExpression(string name, SortDirection direction) { this.name = name; this.direction = direction; }

Actualiza con el código de Jon Skeet y también con toda la clase. GetData () simplemente está llenando el objeto con x número de registros.

public class Data { public int Id { get; set; } public Guid gId { get; set; } public string Name { get; set; } public string Phone { get; set; } public string Address { get; set; } public DateTime Created { get; set; } public string SortMe { get; set; } public static List<Data> GetFakeData(int start, int numberToFetch, IList<SortExpression> sortExpressions, IList<FilterExpression> filterExpressions, out int totalRecords) { DataCollection items = GetData(); IEnumerable<Data> query = from item in items select item; bool sortExpressionsExist = sortExpressions != null; if (sortExpressionsExist) { // Won''t be read in the first iteration; will be written to IOrderedEnumerable<Data> orderedQuery = null; for (int i = 0; i < sortExpressions.Count; i++) { // Avoid single variable being captured: capture one per iteration. // Evil bug which would be really hard to find :) int copyOfI = i; // Tailor "object" depending on what GetProperty returns. Func<Data, object> expression = item => item.GetType().GetProperty(sortExpressions[copyOfI].Name); if (sortExpressions[i].Direction == SortDirection.Ascending) { orderedQuery = (i == 0) ? query.OrderBy(expression) : orderedQuery.ThenBy(expression); } else { orderedQuery = (i == 0) ? query.OrderByDescending(expression) : orderedQuery.ThenByDescending(expression); } } query = orderedQuery; } bool filterExpressionsExist = filterExpressions != null; if (filterExpressionsExist) { foreach (var filterExpression in filterExpressions) { query.Where(item => item.GetType().GetProperty(filterExpression.ColumnName).GetValue(item, null).ToString().Contains(filterExpression.Text)); } } totalRecords = query.Count(); return query.Skip(start).Take(numberToFetch).ToList<Data>(); } }

No parece estar haciendo nada. Compila, sin errores, solo que no clasifica. ¿Algunas ideas?


Hay dos problemas. El primero es al que otros aludieron: debe usar el valor devuelto por OrderBy etc. El segundo es que cada vez que llama a OrderBy , se agrega un nuevo pedido "primario". Realmente quieres ThenBy después de que se haya aplicado el primer pedido. Eso lo hace bastante feo, desafortunadamente. Todavía es bastante feo después de una refactorización, pero no está tan mal ...

IEnumerable<Data> query = from item in items select item; if (sortExpressionsExist) { // Won''t be read in the first iteration; will be written to IOrderedEnumerable<Data> orderedQuery = null; for (int i = 0; i < sortExpressions.Count; i++) { // Avoid single variable being captured: capture one per iteration. // Evil bug which would be really hard to find :) int copyOfI = i; // Tailor "object" depending on what GetProperty returns. Func<Data, object> expression = item => item.GetType() .GetProperty(sortExpressions[copyOfI].Name) .GetValue(item, null); if (sortExpressions[i].Direction == SortDirection.Ascending) { orderedQuery = (i == 0) ? query.OrderBy(expression) : orderedQuery.ThenBy(expression); } else { orderedQuery = (i == 0) ? query.OrderByDescending(expression) : orderedQuery.ThenByDescending(expression); } } query = orderedQuery; }


La consulta no es mutable, por lo que OrderBy devuelve un nuevo objeto. Debe hacer la misma llamada, pero agregue "query =" al principio.

query = query.OrderBy(item => item.GetType().GetProperty(sortExpressions[i].Name));


Los ''operadores'' de OrderBy / OrderByDescending funcionan como String.ToUpper (), es decir, toman lo que se invoca y producen una ''copia'' que tiene lo que pediste.

En otras palabras, en lugar de decir:

query.Orderby(item->item.X)

deberías hacer

query = query.Orderby(item->item.X)

o

sortedResult = query.Orderby(item->item.X)

[Y como lo señala Jon Skeet, usa ThenBy / ThenByDescending como en su respuesta]


OrderBy devuelve un nuevo IEnumerable, por lo que debe hacer algo como:

IEnumerable<Data> results = query.OrderBy(item => item.GetType().GetProperty(sortExpressions[i].Name));


OrderBy en IEnumerable devuelve un IOrderedEnumerable. No los ordena en línea. Así que obtenga el valor de retorno de su .OrderBy y estará bien.