orderbyascending - order by with linq c#
Ampliación del pedido dinámico de Lingra de Marc Gravell (1)
Apuesto a que el tipo de q
es IQueryable<T>
y no IOrderedQueryable<T>
. Solo cambiar la firma debería funcionar, porque comienzas con OrderBy
.
Entonces necesitarás un IOrderedQueryable<T>
para los ThenBy
s. Puedes simplemente IOrderedQueryable<T>
, porque sabes con certeza que tienes un IOrderedQueryable<T>
de la llamada anterior a OrderBy
o ThenBy
.
Si no te gusta la idea del elenco, necesitas algunos cambios:
public IOrderedQueryable<T> ExecuteOrderBys<T>(this IQueryable<T> source)
{
if(!this.Orderings.Any())
throw new InvalidOperationException("You need to add orderings");
IOrderedQueryable<T> ordered;
if (this.Orderings[0].Descending)
ordered = LinqHelper.OrderByDescending(source, this.Orderings[0].Field);
else
ordered = LinqHelper.OrderBy(source, this.Orderings[0].Field);
foreach(var ordering in this.Orderings.Skip(1))
{
if (ordering.Descending)
ordered = LinqHelper.ThenByDescending(source, ordering.Field);
else
ordered = LinqHelper.ThenBy(source, ordering.Field);
}
return ordered;
}
Tenga en cuenta que su código fallará espectacularmente si no agrega ningún orden, debido a la IOrderedQueryable<T>
a IOrderedQueryable<T>
al final. Podría cambiar el tipo de devolución a IQueryable<T>
(que pierde la capacidad de "adjuntar" más OrderBys más adelante), o lanzar si no hay ordenamientos, como hice yo.
Encontré el orden dinámico de Marc Gravell genial:
Dynamic LINQ OrderBy en IEnumerable <T>
Lo puse en una clase, LinqHelper
. En esta clase también he creado dos clases nuevas, de modo que en mi código puedo hacer esto:
var q = db.tblJobHeaders;
LinqHelper.OrderByCollection OBys = new LinqHelper.OrderByCollection();
OBys.AddOrderBy("some field", true);
OBys.AddOrderBy("anotherfield", false);
OBys.ExecuteOrderBys(q);
Las clases para lograr esto son:
/// <summary>
/// A collection of order bys
/// </summary>
public class OrderByCollection
{
private ArrayList Orderings = new ArrayList();
public OrderByCollection(){ }
/// <summary>
/// Add an order by to this collection
/// </summary>
public void AddOrderBy(string Field, bool Descending)
{
OrderByObj NewObj = new OrderByObj(Descending, Field);
this.Orderings.Add(NewObj);
}
/// <summary>
/// Executes the order bys
/// </summary>
public IOrderedQueryable<T> ExecuteOrderBys<T>(this IOrderedQueryable<T> source)
{
int ExecutionIndex = 0;
foreach (OrderByObj O in this.Orderings)
{
if (ExecutionIndex == 0)
{
if (O.Descending)
source = LinqHelper.OrderByDescending(source, O.Field);
else
source = LinqHelper.OrderBy(source, O.Field);
}
else
{
if (O.Descending)
source = LinqHelper.ThenByDescending(source, O.Field);
else
source = LinqHelper.ThenBy(source, O.Field);
}
ExecutionIndex++;
}
return (IOrderedQueryable<T>)source;
}
}
/// <summary>
/// An order by object
/// </summary>
private class OrderByObj
{
public bool Descending { get; set; }
public string Field { get; set; }
public OrderByObj(bool IsDescending, string DatabaseField)
{
this.Descending = IsDescending;
this.Field = DatabaseField;
}
}
Sin embargo, soy bastante nuevo para pasar Linq vars a funciones (lo que me confunde un poco). Actualmente recibo el error:
OBys.ExecuteOrderBys(q);
Que da el error:
Los argumentos de tipo para el método ''LinqHelper.OrderByCollection.ExecuteOrderBys (System.Linq.IOrderedQueryable)'' no se pueden deducir del uso. Intente especificar los argumentos de tipo explícitamente.
Estoy un poco confundido acerca de esto si alguien pudiera ayudarme, ¿estoy pasando la var q
apropiadamente y luego la regreso correctamente?