programing

Efcore: MaxAsync를 수행할 때 시퀀스에 요소가 없습니다.

bestprogram 2023. 9. 4. 20:30

Efcore: MaxAsync를 수행할 때 시퀀스에 요소가 없습니다.

저는 ascore API 프로젝트에서 efcore를 사용하고 있습니다.저는 가장 높은 주문 지수를 찾아야 합니다.

예:

데이터 테이블:Id, ForeignId, OrderIndex

그래서 제가 하고 있는 것은:

var highestOrderIndex = await _context
                .ExampleDbSet
                .Where(x =>
                    x.ForeignId == foreignId)
                .MaxAsync(x =>
                    x.OrderIndex);

문제는 예제 db 집합에 0개의 요소가 포함되어 있는 경우입니다.이 경우 예외가 발생합니다.Sequence contains no element.

이것을 하는 우아한 방법이 있습니까?데이터베이스에서 모든 요소를 가져오고 싶지 않기 때문입니다.그리고 비동기식이어야 합니다.

감사해요.

실제로 다음과 같은 집계 방법을 활용하여 매우 우아하고(그리고 단일 데이터베이스 쿼리만 실행하기 때문에 다른 답변에서 제안된 것에 비해 더 성능이 우수합니다).Min,Max던지다Sequence contains no elementnull이 아닌 오버로드와 함께 사용되는 경우에만 예외가 발생하지만 null이 가능한 오버로드는 단순히 반환됩니다.null대신.

따라서 null이 아닌 속성 유형을 해당 null로 승격하기만 하면 됩니다.예를 들어, 만약에OrderIndex유형은int당신의 질문에 대한 유일한 변경 사항은

.MaxAsync(x => (int?)x.OrderIndex);

이렇게 하면 수신 변수의 유형도 변경됩니다.highestOrderIndex로.int?다음을 확인할 수 있습니다.null그리고 그에 따라 반응하거나, 당신은 단순히 총 함수 호출을 결합할 수 있습니다.??연산자 및 일부 기본값 제공(예:

var highestOrderIndex = (await _context.ExampleDbSet
    .Where(x => x.ForeignId == foreignId)
    .MaxAsync(x => (int?)x.OrderIndex)) ?? -1; // or whatever "magic" number works for you

하는 것AnyAsync그 다음에MaxAsync두 개의 개별 데이터베이스 호출이 발생합니다.시퀀스에 "기본" 최소값이 포함되어 있는지 확인하여 하나로 압축할 수 있습니다.이것은 데이터베이스 코드뿐만 아니라 Linkq Max/Min 메서드를 사용하는 모든 곳에서 유용한 트릭입니다.

context.ExampleDbSet
    .Where(w => w.ForeignId == foreignId)
    .Select(s => s.OrderIndex)
    .Concat(new[] { 0 })
    .MaxAsync();

보다 약간 더 나은 성능을 가진 또 다른 방법입니다.MaxAsync기본값이 가져올 값인 경우 결과가 없는 경우:

var highestOrderIndex = await _context.ExampleDbSet
    .Where(x => x.ForeignId == foreignId)
    .OrderByDescending(x => x.OrderIndex)
    .Select(x => x.OrderIndex)
    .FirstOrDefaultAsync();

TOPAggregate 함수보다 빠릅니다. SQL Server의 실행 계획을 확인하십시오.

레코드가 존재하는지 여부와 존재하는지 여부를 확인한 후 최대값을 찾을 수 있습니다.이와 같은 것:

var query = _context.ExampleDbSet
                .Where(x => x.ForeignId == foreignId);

var itemsExist = await query.AnyAsync();
int maxOrderIndex = 0;

if(itemsExist)
{
    maxOrderIndex = await query.MaxAsync(x => x.OrderIndex);
}

여기서는 데이터베이스에서 모든 항목을 검색할 필요가 없으며 훨씬 빠른 레코드가 있는지 확인하고 메서드를 비동기식으로 유지할 수도 있습니다.

MaxAsync 앞에 DefaultIf Empty 및 Select를 사용할 수 있습니다.

        var highestOrderIndex = await _context
            .ExampleDbSet
            .Where(x =>
                x.ForeignId == foreignId)
            .Select(x => x.OrderIndex)
            .DefaultIfEmpty() // default is 0 if OrderIndex is int or long
             // .DefaultIfEmpty(-1) // default is -1
            .MaxAsync();

언급URL : https://stackoverflow.com/questions/54098087/ef-core-sequence-contains-no-element-when-doing-maxasync