IT

순서가 오름차순이고 널이 마지막 필요하는 널 열에 의해 LINQ 순서

lottoking 2020. 7. 14. 07:55
반응형

순서가 오름차순이고 널이 마지막 필요하는 널 열에 의해 LINQ 순서


가격별로 제품 목록을 강화합니다.

결과 집합은 열별로 가격을 기준으로 제품을 계획해야합니다 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

정렬 된 매번 컬렉션을 다시 정렬하는 별도의 작업입니다.

다음부터 시작해야합니다.


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;

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


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

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

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

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

작동하는 유일한 이유는 첫 번째 정렬 OrderBy()bool값 때문입니다. true/ false. false먼저 결과는 true결과 (널 (NULL 허용))를 따르고 ThenBy()이 아닌 값을 알파벳순으로 정렬합니다.

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

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

경우 SomeString널 (null)이, 그것으로 대체 "z"되고 순으로 다음 종류 다.

참고 : "z".NET과 같은 z- 값 보다 먼저 가기 때문에 이것은 인 솔루션이 아닙니다 zebra.

2016 년 9 월 6 일 업데이트 - @ 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);

이에 대한 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으로 테스트하지 않습니다.


다음은 keySelector의 속성을 정렬하려는 경우 null을 확인하는 확장 메소드입니다.

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

다음과 같이 간단하게 사용하십시오.

var sortedList = list.NullableOrderBy(x => x.someObject, y => y.someObject?.someProperty);

참고 URL : https://stackoverflow.com/questions/6461479/linq-order-by-null-column-where-order-is-ascending-and-nulls-should-be-last

반응형