2010-07-23 4 views
3

IQueryable에 대한 쿼리를 동적으로 정렬하고 정렬하려면 여러 열 (오름차순 또는 내림차순) 정렬이 가능합니다. 나는 다음과 같은 일반적인 기능을 작성했습니다 : 그럼 난 사용자가 분류 요청하는 각 열에 대해, 루프에서이 함수를 호출 오름차순 및LINQ : 많은 열을 동적으로 정렬

내림차순 :

private IQueryable<T> ApplySorting<T,U>(IQueryable<T> query, Expression<Func<T, U>> predicate, SortOrder order) 
    { 
     if (order == SortOrder.Ascending) 
     { 
      { 
       return query.OrderBy<T, U>(predicate); 
      } 
     } 
     else 
     { 
      { 
       return query.OrderByDescending<T, U>(predicate); 
      } 
     } 
    } 

SORTORDER 내 간단한 2 개 값을 열거합니다. 그러나 나는 그것이 항상 마지막 열에 정렬하기 때문에 다른 것들을 무시하고 실패한 것으로 나타났습니다.

var q = db.MyType.OrderBy(x=>x.Col1).ThenBy(y=>y.Col2); //etc. 

그러나 나는 그것이 일반적인 방법을 만들 수 있습니다

는 다음 나는 올바른 사용이 그래서 IOrderedQueryable에 'ThenBy'방법이있다 발견? 나는 쿼리가 IOrderedQueryable인지 테스트하려고했으나 가장 단순한 var q = x에서 db.MyType select x

나는 왜 이런 식으로 설계되었는지 전혀 모른다. 무엇이 잘못 :

var q = db.MyType.OrderBy(x=>x.Col1).OrderBy(y=>y.Col2); //etc. 

+0

나는 (.. .. Col2의). 그들이 .OrderBy (.. COL1를 ..)하지 않는있는 OrderBy 가정 그들이 의도 한 최종 결과가있는 경우 더 좋은 방법을 알고 없습니다이기 때문이다 비행 Col1에 의해 주문한 다음, Col2에 의해 전체 목록을 다시 주문하십시오; Col1 다음에 Col2의 하위 순서 (의도 한대로) –

+0

처음으로 쿼리 집합을 반복 할 때까지 아무 것도 수행되지 않습니다 .OrderBy를 쓸 때 쿼리 실행이 지연됩니다. – PawelRoman

답변

0

총 추측 훨씬 직관적입니다,하지만 당신은 이런 일을 할 수 있습니까?

query.OrderBy(x => 1).ThenBy<T,U>(predicate) 

따로 구문 오류가, 아이디어는 아무 영향을주지 않는있는 OrderBy()를하는 것입니다, 다음

+0

좋은 해킹, 그리고 그 일을해야하지만, 여전히 그것은 단지 해킹이야. linq 저자가 그런 시나리오를 생각하지 않았다는 것을 믿는 것은 어렵습니다. 그런 일을 파이썬/django 너무 사소한입니다 ... – PawelRoman

1

당신은 단지 확인하는 데 필요한 .ThenBy() 메서드 호출에서 실제 일을 쿼리가 이미 주문 된 경우 :

private IQueryable<T> ApplySorting<T,U>(IQueryable<T> query, Expression<Func<T, U>> predicate, SortOrder order) 
{ 
    var ordered = query as IOrderedQueryable<T>; 
    if (order == SortOrder.Ascending) 
    { 
     if (ordered != null) 
      return ordered.ThenBy(predicate); 
     return query.OrderBy(predicate); 
    } 
    else 
    { 
     if (ordered != null) 
      return ordered.ThenByDescending(predicate); 
     return query.OrderByDescending(predicate); 
    } 
} 
+1

이 나던 작업.내가 말했듯이, 쿼리는 항상 IOrderedQueryable 타입이고, 이벤트는 x에서 가장 단순하다. select x; – PawelRoman

0

전 래퍼를 작성하고 내부적으로 linq 확장 메소드를 사용합니다.

var resultList = presentList 
     .MyOrderBy(x => x.Something) 
     .MyOrderBY(y => y.SomethingElse) 
     .MyOrderByDesc(z => z.AnotherThing) 

public IQueryable<T> MyOrderBy(IQueryable<T> prevList, Expression<Func<T, U>> predicate) { 

     return (prevList is IOrderedQueryable<T>) 
      ? query.ThenBy(predicate) 
      : query.OrderBy(predicate); 
} 

public IQueryable<T> MyOrderByDesc(IQueryable<T> prevList, Expression<Func<T, U>> predicate) { 

     return (prevList is IOrderedQueryable<T>) 
      ? query.ThenByDescending(predicate) 
      : query.OrderByDescending(predicate); 
} 

PS :

public static class DynamicExtentions 
{ 
    public static IEnumerable<T> DynamicOrder<T>(this IEnumerable<T> data, string[] orderings) where T : class 
    { 
     var orderedData = data.OrderBy(x => x.GetPropertyDynamic(orderings.First())); 
     foreach (var nextOrder in orderings.Skip(1)) 
     { 
      orderedData = orderedData.ThenBy(x => x.GetPropertyDynamic(nextOrder)); 
     } 
     return orderedData; 
    } 

    public static object GetPropertyDynamic<Tobj>(this Tobj self, string propertyName) where Tobj : class 
    { 
     var param = Expression.Parameter(typeof(Tobj), "value"); 
     var getter = Expression.Property(param, propertyName); 
     var boxer = Expression.TypeAs(getter, typeof(object)); 
     var getPropValue = Expression.Lambda<Func<Tobj, object>>(boxer, param).Compile();    
     return getPropValue(self); 
    } 
} 

예 :

var q =(myItemsToSort.Order(["Col1","Col2"]); 

참고 : 확인되지 않은 IQueryable 제공 나는 동적 멀티 순서에 코드를

+0

이 코드를 테스트하면 Iterable 은 항상 IOrderedQueryable 이므로 ThenBy 함수는 항상 호출되며 OrderBy는 호출되지 않습니다. 이것은 필자가 여기에 글을 쓰기 전에 어떻게 구현하려했는지와 비슷하다. – PawelRoman

0

확장을 테스트하지 않았다 번역 할 수 있음

0

그냥 먼저 OrderBy을 고정시킨 다음 항상 항상 ThenBy이됩니까?

OrderColumn[] columnsToOrderby = getColumnsToOrderby(); 
IQueryable<T> data = getData(); 

if(!columnToOrderBy.Any()) { } 
else 
{ 
    OrderColumn firstColumn = columnsToOrderBy[0]; 
    IOrderedEnumerable<T> orderedData = 
     firstColumn.Ascending 
     ? data.OrderBy(predicate) 
     : data.OrderByDescending(predicate); 

    for (int i = 1; i < columnsToOrderBy.Length; i++) 
    { 
     OrderColumn column = columnsToOrderBy[i]; 
     orderedData = 
      column.Ascending 
      ? orderedData.ThenBy(predicate) 
      : orderedData.ThenByDescending(predicate); 
    } 
}