LINQ에서 여러 "주문"


1582

두 개의 테이블이 movies있으며 먼저 categoryIDcategories 로 정렬 한 다음 Name 별로 정렬 된 목록을 얻습니다 .

영화 테이블에는 ID와 Name 이라는 세 개의 열이 있습니다. 카테고리 테이블에는 ID 및 Name의 두 열이 있습니다.

나는 다음과 같은 것을 시도했지만 작동하지 않았다.

var movies = _db.Movies.OrderBy( m => { m.CategoryID, m.Name })

괄호 안의 람다 식은 항목을 주문하는 데 사용할 수있는 값을 반환해야합니다. m.CategoryID는 항목을 주문하는 데 사용할 수있는 숫자입니다. 그러나 "m.CategoryID, m.Name"은이 문맥에서 의미가 없습니다.
— chiccodoro

9
. 그럼 당신이 찾고있는 것입니까?
— eka808

만일 우연히 당신이 그것들을 내림차순으로 정렬하고 싶다면 여기 로 가십시오.
— RBT

답변:


2831

이것은 당신을 위해 작동해야합니다 :

var movies = _db.Movies.OrderBy(c => c.Category).ThenBy(n => n.Name)

4
물론 답을 주셔서 감사합니다 ... 그러나 "orderBy"를 두 번 Var movies = _db.Movies.Orderby(c => c.Category).ThenBy(n => n.Name) 사용하는 대신 Var movies = _db.Movies.Orderby(c => c.Category).OrderBy(n => n.Name)결과가 다른 이유는 무엇입니까?

147
두 번째 "있는 OrderBy는"해당 항목 최초의 "있는 OrderBy"과 재주문 결과 컬렉션을 통해 작동하기 때문에 @devendra는, 결과는 다릅니다

68
나는 지구상에서 어떻게 알지 못하고이 세상을 떠났 ThenBy습니까?! ( 편집 : .NET 4.0에서 소개 된 것처럼 보이며 눈에 띄지 않게 미끄러졌습니다.)
— Jordan Gray

13
이것은 LINQ가 추가 된 이후에있었습니다. 이 답변은 .NET 4.0 이전 버전입니다.
— Nathan W

10
그렇다. 나는 문서 페이지 의 3.5 버전 드롭 다운에 있지 않다고 성급하게 결론 지었다 . 버전 정보를 철저히 조사해야했습니다. 수정 해 주셔서 감사합니다. :)
— Jordan Gray

594

람다가 아닌 쿼리 구문 LINQ를 사용하여 다음을 수행 할 수 있습니다.

var movies = from row in _db.Movies 
             orderby row.Category, row.Name
             select row;

[주석을 수정하려면 편집] 정렬 순서를 제어하려면 키워드 ascending(기본적으로 유용하지는 않지만) 또는을 사용하십시오 descending.

var movies = from row in _db.Movies 
             orderby row.Category descending, row.Name
             select row;

1
이 구문에서 내림차순과 비 내림을 앞뒤로 뒤집을 수있는 방법이 없습니까?
— ehdv

1
실제로 귀하의 답변은에 해당합니다 _db.Movies.Orderby(c => c.Category).OrderBy(n => n.Name). 더 정확한 것은from row in _db.Movies orderby row.Category descending orderby row.Name select row
— Lodewijk

9
@ Lodewijk : 나는 당신이 정확히 거꾸로 있다고 생각합니다. 예를 들어 row.Name은 기본 열이고 row.Category secondary는에 해당 _db.Movies.Orderby(c => c.Category).OrderBy(n => n.Name)합니다. 제공하는 두 스 니펫은 OP가 아닌 서로 동일합니다.
— Scott Stafford

6
Linq에 SQL 구문을 사용할 때의 유일한 단점은 모든 기능이 지원되는 것은 아니며 전부는 아니라는 것입니다.
— Joshua G

74

새로운 걸 더하다":

var movies = _db.Movies.OrderBy( m => new { m.CategoryID, m.Name })

그것은 내 상자에서 작동합니다. 정렬하는 데 사용할 수있는 것을 반환합니다. 두 개의 값을 가진 객체를 반환합니다.

다음과 같이 유사하지만 결합 된 열을 기준으로 정렬하는 것과 다릅니다.

var movies = _db.Movies.OrderBy( m => (m.CategoryID.ToString() + m.Name))

21
숫자로 사용할 때주의하십시오.
— WoF_Angel

7
필요에 따라 OrderByDescending 및 ThenBy 또는 OrderBy 및 ThenByDescending을 사용할 수 있습니다.
— Ali Shah Ahmed

6
나는 확신이 있어요 .OrderBy( m => new { m.CategoryID, m.Name })및 .OrderBy( m => new { m.Name, m.CategoryID })의도 우선 순위를 존중하기보다는 동일한 결과를 생성합니다. 때로는 우연의 일치로 원하는 순서를 제시하는 것처럼 보일 것입니다. 또한 m.CategoryID.ToString() + m.NameCategoryID가 인 경우 잘못된 주문이 생성됩니다 int. 예를 들어, id = 123, name = 5times 인 항목은 id = 1234 뒤에, name = something 뒤에 나타납니다. int 비교가 발생할 수있는 문자열 비교는 비효율적입니다.
— AaronLS

7
익명 형식으로 주문하려고하면 "적어도 하나의 개체가 IComparable을 구현해야합니다."라는 메시지와 함께 ArgumentException이 발생합니다. 나는 이것을 할 때 다른 사람들이 비교자를 선언해야한다는 것을 알았습니다. stackoverflow.com/questions/10356864/…를 참조하십시오 .
— Robert Gowland

4
이것은 절대적으로 잘못입니다. 익명 유형의 속성에 대한 순서가 없기 때문에 ICompariable 구현이없는 새로운 익명 유형에 의한 순서는 작동 할 수 없습니다. CategoryID를 먼저 정렬할지 또는 Name을 먼저 정렬할지 여부는 알지 못합니다 (반대 순서로 정렬해야하는 경우는 제외).
— Triynko

29

DataContext에서 다음 행을 사용하여 DataContext의 SQL 활동을 콘솔에 로그하십시오. 그러면 linq 문이 데이터베이스에서 요청한 내용을 정확하게 볼 수 있습니다.

_db.Log = Console.Out

다음 LINQ 문 :

var movies = from row in _db.Movies 
             orderby row.CategoryID, row.Name
             select row;

과

var movies = _db.Movies.OrderBy(m => m.CategoryID).ThenBy(m => m.Name);

다음 SQL을 생성하십시오.

SELECT [t0].ID, [t0].[Name], [t0].CategoryID
FROM [dbo].[Movies] as [t0]
ORDER BY [t0].CategoryID, [t0].[Name]

반면 Linq에서 OrderBy를 반복하면 결과 SQL 출력이 반대로 나타납니다.

var movies = from row in _db.Movies 
             orderby row.CategoryID
             orderby row.Name
             select row;

과

var movies = _db.Movies.OrderBy(m => m.CategoryID).OrderBy(m => m.Name);

다음 SQL을 생성하십시오 (이름 및 CategoryId가 전환됨).

SELECT [t0].ID, [t0].[Name], [t0].CategoryID
FROM [dbo].[Movies] as [t0]
ORDER BY [t0].[Name], [t0].CategoryID

24

나는 확장 메소드 (아래)를 만들었으므로 IQueryable이 이미 주문되어 있는지 걱정할 필요가 없습니다. 여러 속성으로 주문하려면 다음과 같이하십시오.

// We do not have to care if the queryable is already sorted or not. 
// The order of the Smart* calls defines the order priority
queryable.SmartOrderBy(i => i.Property1).SmartOrderByDescending(i => i.Property2);

이것은 정렬 할 속성 목록에서 순서를 동적으로 생성 할 때 특히 유용합니다.

public static class IQueryableExtension
{
    public static bool IsOrdered<T>(this IQueryable<T> queryable) {
        if(queryable == null) {
            throw new ArgumentNullException("queryable");
        }

        return queryable.Expression.Type == typeof(IOrderedQueryable<T>);
    }

    public static IQueryable<T> SmartOrderBy<T, TKey>(this IQueryable<T> queryable, Expression<Func<T, TKey>> keySelector) {
        if(queryable.IsOrdered()) {
            var orderedQuery = queryable as IOrderedQueryable<T>;
            return orderedQuery.ThenBy(keySelector);
        } else {
            return queryable.OrderBy(keySelector);
        }
    }

    public static IQueryable<T> SmartOrderByDescending<T, TKey>(this IQueryable<T> queryable, Expression<Func<T, TKey>> keySelector) {
        if(queryable.IsOrdered()) {
            var orderedQuery = queryable as IOrderedQueryable<T>;
            return orderedQuery.ThenByDescending(keySelector);
        } else {
            return queryable.OrderByDescending(keySelector);
        }
    }
}

1
이 답변은 금입니다! queryable.IsOrdered ()에 대한 검사를이 게시물의 답변과 결합하여 정렬 방향을 취하는 단일 메소드를 갖습니다. stackoverflow.com/questions/388708
— SwissCoder

1
이런 식으로 Linq 구현은 처음부터 진행되어야합니다! OrderBy는 잘못 설계되었습니다 ...
— Andrzej Martyna

1
@Marie 사용 사례를 명확하게 이해하지 못했습니다. 예를 들어 속성 ​​목록에서 순서를 어떻게 동적으로 작성합니까? 이것이 유일한 방법입니다. 공감하거나 재고하지 마십시오. 감사합니다.
— sjkm

그럴 수 있지. 여전히 혜택을 볼 수 없지만 투표권을 다시 가져갑니다
— Marie

이 작업을 수행 할 nullable datetime
— 것인가

16

가장 쉬운 방법은 아니지만 LINQ를 사용하여이 작업을 수행하는 방법이 하나 이상 있습니다. 를 사용하는 OrberBy()메소드를 사용 하여이를 수행 할 수 있습니다 IComparer. 먼저 당신은을 구현해야 IComparer에 대한 Movie이 같은 클래스 :

public class MovieComparer : IComparer<Movie>
{
    public int Compare(Movie x, Movie y)
    {
        if (x.CategoryId == y.CategoryId)
        {
            return x.Name.CompareTo(y.Name);
        }
        else
        {
            return x.CategoryId.CompareTo(y.CategoryId);
        }
    }
}

그런 다음 다음 구문으로 영화를 주문할 수 있습니다.

var movies = _db.Movies.OrderBy(item => item, new MovieComparer());

항목 중 하나에 대해 순서를 내림차순으로 전환 해야하는 경우 그에 따라 Compare() 방법 내에서 x와 y를 전환하십시오 MovieComparer.


1
나는 다른 알고리즘을 사용할 준비가 된 다른 비교 객체를 포함하여 비교로 이상한 일을 할 수 있기 때문에 이보다 더 일반적이라고 생각합니다. 이것은 IComparable 인터페이스를 구현하는 클래스를 작성하는 방법을 배우기 전에 내가 선호하는 솔루션보다 낫습니다.
— Gerard ONeill

1
2012 (.NET 버전 4.5) 이후 클래스를 MovieComparer직접 만들 필요는 없습니다 . 대신에 할 수 있습니다 _db.Movies.OrderBy(item => item, Comparer<Movie>.Create((x, y) => { if (x.CategoryId == y.CategoryId) { return x.Name.CompareTo(y.Name); } else { return x.CategoryId.CompareTo(y.CategoryId); } }));. 물론 if... 대신에 하나의 표현식으로 논리를 작성하려는 경우 else라마 (x, y) => expr가 더 간단해질 수 있습니다.
— Jeppe Stig Nielsen

3

일반 리포지토리를 사용하는 경우

> lstModule = _ModuleRepository.GetAll().OrderBy(x => new { x.Level,
> x.Rank}).ToList();

그밖에

> _db.Module.Where(x=> ......).OrderBy(x => new { x.Level, x.Rank}).ToList();

1
익명 표현은 엔티티 프레임 워크 코어에 의해 로컬로 구문 분석됩니다. LINQ 표현식을 번역 할 수 없으며 로컬에서 평가됩니다.
— alhpe
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.