with orderbydescending orderbyascending ordenar lista c# sql-order-by iqueryable

orderbydescending - order by with linq c#



Determine si un IQueryable<T> ha sido ordenado o no (6)

En realidad, usted puede.

El primer problema que detecto en tu código es que estás enviando la colección a IQueryable sin ninguna razón para hacerlo.

El siguiente fragmento de código:

var numbers = new[] {1, 5, 6, 87, 3}; Console.Write(numbers is IOrderedEnumerable<int>); var ordered = numbers.OrderBy(c => c); Console.Write(ordered is IOrderedEnumerable<int>);

Ni siquiera necesita ejecutarse: la primera comprobación le da una advertencia de tiempo de diseño que dice que esta expresión nunca será cierta.

De todos modos, si lo ejecuta, le dará Falso para la primera comprobación y Verdadero para la segunda comprobación.

Puede hacer lo mismo con IQueryable<T> e IOrderedQueryable<T> siempre que realmente esté usando ese tipo y no le asigne una colección.

¿Hay alguna manera de saber si un IQueryable<T> ha sido ordenado (usando OrderBy o OrderbyDescending )?

Así que sé si llamar a OrderBy o ThenBy en la colección.

IQueryable<Contact> contacts = Database.GetContacts();

Intenté contacts is IOrderedQueryable<Contact> , pero siempre es cierto.

Edición : acabo de cambiar mi ejemplo, el anterior no estaba realmente mostrando mi punto. Suponga que GetContacts utiliza Entity Framework y simplemente devuelve todos los registros de una tabla.

Más adelante, aplico varias funciones a los contacts , no tengo conocimiento de lo que hacen esas funciones. Pueden ordenar o filtrar el IQueryable<Contact> .

Cuando recupere la colección, necesito ordenarla una vez más. Para hacerlo, necesito saber si necesito llamar a OrderBy o ThenBy . Así que no reordeno toda la colección si ya ha sido ordenada.


Es posible. Aquí hay un método de extensión:

public static bool IsOrdered<T>(this IQueryable<T> queryable) { if (queryable == null) { throw new ArgumentNullException("queryable"); } return queryable.Expression.Type == typeof(IOrderedQueryable<T>); }



Nunca sabrá si los objetos se han pedido correctamente, a menos que usted mismo verifique el pedido. Es fácil ver que su ejemplo no está ordenado, porque los números tienen un orden natural, pero IQueryable es un genérico, lo que significa que puede manejar diferentes tipos de objetos. El orden de los objetos de usuario de decir (nombre, apellido, fecha y fecha y fecha de pago) tiene un orden arbitrario, por lo que el orden en el que se devuelven no es necesariamente el orden que usted está buscando. (¿Cuál se considera el campo primario para la clasificación? Depende de su necesidad). Entonces, en teoría, la pregunta "¿Están ordenados" siempre podría ser "Sí"? El orden que está buscando puede ser muy diferente de lo que devuelve el sistema.


Puede examinar el ToString () de su consulta para averiguar si se utiliza Order By.

Cuando se produce una unión, el ToString de IQueryable pone paréntesis al principio y al final de la consulta interna. Entonces, si encuentra los últimos paréntesis de cierre, puede verificar si su consulta más externa tiene una cláusula Ordenar por.

private bool isOrdered(IQueryable Data) { string query = Data.ToString(); int pIndex = query.LastIndexOf('')''); if (pIndex == -1) pIndex = 0; if (query.IndexOf("ORDER BY", pIndex) != -1) { return true; } return false; }

Sé que está extremadamente sucio, pero funciona en todos mis casos y no puedo pensar en un caso excepcional.


Sí, puede inspeccionar el árbol IQueryable.Expression para ver si llama a alguno de los métodos OrderBy/ThenBy . Los árboles de expresiones se pueden examinar derivando una clase de ExpressionVisitor .

Existe un OrderingMethodFinder interno en System.Web , que puede adaptar. Esto es lo que se me ocurrió:

// Adapted from internal System.Web.Util.OrderingMethodFinder http://referencesource.microsoft.com/#System.Web/Util/OrderingMethodFinder.cs class OrderingMethodFinder : ExpressionVisitor { bool _orderingMethodFound = false; protected override Expression VisitMethodCall(MethodCallExpression node) { var name = node.Method.Name; if (node.Method.DeclaringType == typeof(Queryable) && ( name.StartsWith("OrderBy", StringComparison.Ordinal) || name.StartsWith("ThenBy", StringComparison.Ordinal))) { _orderingMethodFound = true; } return base.VisitMethodCall(node); } public static bool OrderMethodExists(Expression expression) { var visitor = new OrderingMethodFinder(); visitor.Visit(expression); return visitor._orderingMethodFound; } }

Úsalo así:

bool isOrdered = OrderingMethodFinder.OrderMethodExists(myQuery.Expression);