순서가 오름차순이고 널이 마지막이어야하는 널 열에 의한 LINQ 순서 orderby

가격별로 제품 목록을 정렬하려고합니다.

결과 집합은 열별로 가격을 기준으로 제품을 나열해야합니다 LowestPrice. 그러나이 열은 널 입력 가능합니다.

목록을 내림차순으로 정렬 할 수 있습니다.

var products = from p in _context.Products
   where p.ProductTypeId == 1
   orderby p.LowestPrice.HasValue descending
   orderby p.LowestPrice descending
   select p;

// returns:    102, 101, 100, null, null

그러나 이것을 오름차순으로 정렬하는 방법을 알 수 없습니다.

// i'd like: 100, 101, 102, null, null


답변

두 열을 모두 같은 순서로 배치하십시오.

orderby p.LowestPrice.HasValue descending, p.LowestPrice

그렇지 않으면 각 orderby는 매번 컬렉션을 다시 정렬하는 별도의 작업입니다.

먼저 값을 가진 것들을 순서대로 정렬해야합니다.


답변

LINQ 쿼리 구문과 LINQ 메서드 호출로 변환되는 방법을 이해하는 데 실제로 도움이됩니다.

그것은 밝혀졌다

var products = from p in _context.Products
               where p.ProductTypeId == 1
               orderby p.LowestPrice.HasValue descending
               orderby p.LowestPrice descending
               select p;

컴파일러에 의해

var products = _context.Products
                       .Where(p => p.ProductTypeId == 1)
                       .OrderByDescending(p => p.LowestPrice.HasValue)
                       .OrderByDescending(p => p.LowestPrice)
                       .Select(p => p);

이것은 당신이 원하는 것이 아닙니다. 이 종류에 의해 Product.LowestPrice.HasValue에서 descending위해 다음과 같은 방법으로 전체 컬렉션을-가 정렬 다시 Product.LowestPricedescending순서.

당신이 원하는 것은

var products = _context.Products
                       .Where(p => p.ProductTypeId == 1)
                       .OrderByDescending(p => p.LowestPrice.HasValue)
                       .ThenBy(p => p.LowestPrice)
                       .Select(p => p);

쿼리 구문을 사용하여 얻을 수 있습니다.

var products = from p in _context.Products
               where p.ProductTypeId == 1
               orderby p.LowestPrice.HasValue descending,
                       p.LowestPrice
               select p;

쿼리 구문에서 메서드 호출로의 변환에 대한 자세한 내용은 언어 사양을 참조하십시오. 진심으로. 읽어.


답변

문자열 값에 대한 해결책은 정말 이상합니다.

.OrderBy(f => f.SomeString == null).ThenBy(f => f.SomeString) 

작동하는 유일한 이유는 첫 번째 표현식 OrderBy()인 정렬 bool값 때문입니다. true/ false. false결과는 먼저 true결과 (널링 가능 항목)를 따르고 널 ThenBy()이 아닌 값을 알파벳순으로 정렬합니다.

따라서 다음과 같이 더 읽기 쉬운 것을 선호합니다.

.OrderBy(f => f.SomeString ?? "z")

SomeStringnull 인 경우 는 대체되어 "z"알파벳순으로 모든 것을 정렬합니다.

참고 :이 "z"같은 z- 값보다 우선하기 때문에 이것은 궁극적 인 해결책이 아닙니다 zebra.

업데이트 9/6/2016-@jornhd 의견에 관해서는, 정말 좋은 솔루션이지만 여전히 약간 복잡하므로 확장 클래스로 래핑하는 것이 좋습니다.

public static class MyExtensions
{
    public static IOrderedEnumerable<T> NullableOrderBy<T>(this IEnumerable<T> list, Func<T, string> keySelector)
    {
        return list.OrderBy(v => keySelector(v) != null ? 0 : 1).ThenBy(keySelector);
    }
}

그리고 간단하게 사용하십시오 :

var sortedList = list.NullableOrderBy(f => f.SomeString);

답변

이 상황에서 다른 옵션이 있습니다. 내 목록은 objList이며 주문해야하지만 null은 끝에 있어야합니다. 나의 결정:

var newList = objList.Where(m=>m.Column != null)
                     .OrderBy(m => m.Column)
                     .Concat(objList.where(m=>m.Column == null));

답변

나는 이것에 대한 LINQ 솔루션을 찾으려고했지만 여기의 답변에서 해결할 수 없었습니다.

내 최종 답변은 다음과 같습니다

.OrderByDescending(p => p.LowestPrice.HasValue).ThenBy(p => p.LowestPrice)

답변

나의 결정:

Array = _context.Products.OrderByDescending(p => p.Val ?? float.MinValue)

답변

이것은 확장 방법을 사용하고 있기 때문에 내가 생각 해낸 것입니다. 또한 내 항목은 문자열이므로 없습니다 .HasValue.

.OrderBy(f => f.SomeString == null).ThenBy(f => f.SomeString)

메모리의 LINQ 2 개체와 함께 작동합니다. EF 또는 DB ORM으로 테스트하지 않았습니다.