LINQ To 엔터티는 마지막 방법을 인식하지 못합니다. 정말?


144

이 쿼리에서 :

public static IEnumerable<IServerOnlineCharacter> GetUpdated()
{
    var context = DataContext.GetDataContext();
    return context.ServerOnlineCharacters
        .OrderBy(p => p.ServerStatus.ServerDateTime)
        .GroupBy(p => p.RawName)
        .Select(p => p.Last());
}

작동하려면 이것을 전환해야했습니다.

public static IEnumerable<IServerOnlineCharacter> GetUpdated()
{
    var context = DataContext.GetDataContext();
    return context.ServerOnlineCharacters
        .OrderByDescending(p => p.ServerStatus.ServerDateTime)
        .GroupBy(p => p.RawName)
        .Select(p => p.FirstOrDefault());
}

p.First()첫 번째 쿼리를 미러링하기 위해 조차 사용할 수 없었습니다 .

왜 그렇게 강력한 ORM 시스템에 기본적인 제한이 있습니까?


IEnumrable 객체를 새 변수에 저장 한 다음 variable.last ()를 반환하십시오. 작동합니다.
Ali.Rashidi

답변:


220

이 제한은 결국 쿼리를 SQL 로 변환해야 하고 SQL에는 SELECT TOP(T-SQL에서는) 있지만 SELECT BOTTOM(아무것도없는 ) 것은 없다는 사실에 기인합니다 .

그래도 쉬운 방법이 있습니다. 내림차순으로 주문한 다음을 수행하십시오 First().

편집 : 다른 공급자는 아마도 다른 구현을 가질 SELECT TOP 1것입니다. 오라클에서는 아마도 더 비슷할 것입니다WHERE ROWNUM = 1

편집하다:

덜 효율적인 다른 대안- 나는 이것을 권장하지 않습니다! - .ToList()전에 데이터 를 호출 .Last()하면 해당 시점까지 빌드 된 LINQ To Entities Expression을 즉시 실행 한 다음 .Last ()가 작동 .Last()합니다. 대신 LINQ to Objects Expression. (그리고 당신이 지적한 것처럼, 그것은 결코 사용되지 않을 수천 개의 레코드와 CPU 구체화 객체의 낭비를 가져올 수 있습니다)

다시 한 번이 작업을 수행하지 않는 것이 좋지만 LINQ식이 실행되는 위치와 시간의 차이를 설명하는 데 도움이됩니다.


LINQ To SQL은이 시나리오를 어떻게 처리합니까?
bevacqua

@Neil 그래 난 내가 ToList를 호출 할 수 있습니다 알고,하지만 난 오히려 단지 다섯 개 개의 레코드로 아래로 필터링 데이터베이스에서 수천 개의 레코드를 검색 할 것
bevacqua

2
쿼리가 작은 결과를 반환한다는 것을 알고 있다면 호출 ToList이 그렇게 나쁘지 않습니다.
Justin Skiles

35

대신 다음을 Last()시도하십시오.

model.OrderByDescending(o => o.Id).FirstOrDefault();

14

Last()Linq 선택기로 교체OrderByDescending(x => x.ID).Take(1).Single()

Linq에서 선호하는 경우 이와 같은 것이 작동합니다.

public static IEnumerable<IServerOnlineCharacter> GetUpdated()
{
    var context = DataContext.GetDataContext();
    return context.ServerOnlineCharacters.OrderBy(p => p.ServerStatus.ServerDateTime).GroupBy(p => p.RawName).Select(p => p.OrderByDescending(x => x.Id).Take(1).Single());
}

1
.FirstOrDefault () 대신 .Take (1) .Single ()을 사용해야 할 이유가 있습니까?
Tot Zam

2
@TotZam 아이템 개수가 정확히 1이 아닌 경우 Single ()에서 예외가 발생하므로 유효한 대체는 .First ()입니다.
MEMark

0

또 다른 방법은 OrderByDescending없이 마지막 요소를 가져 와서 모든 엔티티를로드합니다.

dbSet
    .Where(f => f.Id == dbSet.Max(f2 => f2.Id))
    .FirstOrDefault();

0

LINQ to Entities (및 데이터베이스)는 모든 LINQ 메소드를 지원하지 않기 때문입니다 (자세한 내용은 여기 참조 : http://msdn.microsoft.com/en-us/library/bb738550.aspx ).

여기서 필요한 것은 "마지막"레코드가 "먼저"가되도록 FirstOrDefault를 사용하는 방식으로 데이터를 주문하는 것입니다. 데이터베이스에는 일반적으로 "첫 번째"및 "마지막"과 같은 개념이 없으며 가장 최근에 삽입 된 레코드가 테이블에서 "마지막"인 것과는 다릅니다.

이 방법은 문제를 해결할 수 있습니다

db.databaseTable.OrderByDescending(obj => obj.Id).FirstOrDefault();

-2

AsEnumerable()Select 기능이 작동하기 전에 단일 기능을 추가 했습니다.
예:

return context.ServerOnlineCharacters
    .OrderByDescending(p => p.ServerStatus.ServerDateTime)
    .GroupBy(p => p.RawName).AsEnumerable()
    .Select(p => p.FirstOrDefault());

참조 : https://www.codeproject.com/Questions/1005274/LINQ-to-Entities-does-not-recognize-the-method-Sys


링크의 작업 코드를 답변에 통합하는 것이 좋습니다. 링크 전용 답변은 부정적인 관심을 끌 것입니다. 문제를 해결하고 해결하기 위해 찾은 코드를 추가하여 전체 답변을 제공하십시오. 이는 향후 404 오류로 인해 링크가 작동하지 않는 문제를 해결합니다.
Studocwho

1
내 답변에 예를 추가
Artem Levitin

이 답변의 단점은 "AsEnumerable"서버 측 이전에 모든 결과를 가져온 다음 첫 번째를 선택한다는 것입니다. 이것은 매우 바람직하지 않을 수 있습니다. 합니다 (20K + 기록을 서버 측을 가져되는 인한 결과는 I 그것이 DB 측으로 다시 이동하면, 20+ 초 복용 하였다 여기서 I는, 이하 제보다에서 반환 된 결과 이런 상황에 있었다)
TChadwick
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.