orderbyascending orderby ordenar net multiple lista columns asp ascending asc c# linq

orderby - order by linq c# multiple columns



¿Cómo especifico dinámicamente el argumento Linq OrderBy? (10)

¿Cómo especifico el argumento pasado a orderby usando un valor que tomo como parámetro?

Ex:

List<Student> existingStudends = new List<Student>{ new Student {...}, new Student {...}}

Implementación actual:

List<Student> orderbyAddress = existingStudends.OrderBy(c => c.Address).ToList();

En lugar de c.Address , ¿cómo puedo tomar eso como un parámetro?

Ejemplo

string param = "City"; List<Student> orderbyAddress = existingStudends.OrderByDescending(c => param).ToList();


1) Instalar System.Linq.Dynamic

2) Agregue el siguiente código

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) Escribe tu interruptor para seleccionar la función Lambda

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) Usa tus ayudantes

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

5) Puede usarlo con paginación ( 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); }

Explicación

System.Linq.Dynamic nos permite establecer el valor de cadena en el método OrderBy. Pero dentro de esta extensión, la cadena se analizará en Lambda. Así que pensé que funcionaría si analizamos Lambda para enhebrarlo y dárselo al método OrderBy. ¡Y funciona!


Aquí hay algo que se me ocurrió para lidiar con un descenso descendente condicional. Puede combinar esto con otros métodos para generar el keySelector dinámicamente.

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); }

Uso:

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

Observe que esto le permite encadenar esta extensión .OrderBy con un nuevo parámetro en cualquier 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);


Aquí hay una posibilidad usando la reflexión ...

var param = "Address"; var propertyInfo = typeof(Student).GetProperty(param); var orderByAddress = items.OrderBy(x => propertyInfo.GetValue(x, null));


Esto no le permite pasar una string , como lo pidió en su pregunta, pero aún podría funcionar para usted.

El método OrderByDescending tiene un Func<TSource, TKey> , por lo que puede volver a escribir su función de esta manera:

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

También existen otras sobrecargas para OrderByDescending que toman una Expression<Func<TSource, TKey>> , y / o un IComparer<TKey> . También puede ver esos y ver si le proporcionan algo de uso.


La única solución que funcionó para mí fue publicada aquí https://gist.github.com/neoGeneva/1878868 por neoGeneva.

Volveré a publicar su código porque funciona bien y no me gustaría que se perdiera en el interwebs.

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; }


Llego tarde a la fiesta pero ninguna de estas soluciones funcionó para mí. Estaba ansioso por probar System.Linq.Dynamic, pero no pude encontrar eso en Nuget, ¿tal vez me deprecié? De cualquier manera...

Aquí hay una solución que se me ocurrió. Necesitaba usar dinámicamente una mezcla de OrderBy , OrderByDescending y OrderBy> ThenBy .

Simplemente creé un método de extensión para mi objeto de lista, un poco hacky, lo sé ... No recomendaría esto si fuera algo que estuviese haciendo mucho, pero es bueno para uno.

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); } }


Para ampliar la respuesta con @Icarus : si desea que el tipo de devolución del método de extensión sea IOrderedQueryable en lugar de IQueryable, simplemente puede convertir el resultado de la siguiente manera:

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); }


Puede usar un poco de reflexión para construir el árbol de expresiones de la siguiente manera (este es un método de extensión):

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 es el nombre de la propiedad que desea ordenar y si pasa true como parámetro para desc , ordenará en orden descendente; de lo contrario, se ordenarán en orden ascendente.

Ahora debería poder hacer existingStudents.OrderBy("City",true); o existingStudents.OrderBy("City",false);


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);


  • Agregue el paquete de nugget Dynamite a su código

  • Agregue el espacio de nombre Dynamite.Extensions Ejemplo: usando Dynamite.Extensions;

  • Realice el pedido por consulta como cualquier consulta SQL. Por ejemplo: students.OrderBy ("City DESC, Address"). ToList ();