2010-05-24 3 views
0

시퀀스에서 쿼리 연산자를 호출하면 시퀀스 관련 연산자가 호출됩니다.
연산자를 IEnumerable<>에 호출하면 호출 할 연산자가 Enumerable 클래스에 정의되고 IQueryable<>에서 호출되면 쿼리 가능 클래스에 정의 된 연산자가 호출됩니다.AsEnumerable()은 모든 결과 (LINQ)를 캐시합니까?

Enumerable 클래스에 정의 된 연산자 인 Reverse를 생각해보십시오.
Iqueryable<>에 전화를 걸려면 먼저 AsEnumerable<>() 연산자를 사용하여 먼저 IEnumerable<>으로 변환해야합니다.

db.Countries.OrderBy(cntry=>cntry.CountryName).AsEnumerable().Reverse() 

그러나 반전 연산자는 모든 레코드를 동시에 가져 와서 반대로 할 수 있습니다.
위의 코드에서 모든 레코드가 먼저 메모리에로드되고 Reverse() 연산자가이를 반대로 수행합니까?

+0

예. 결과 집합을 구체화하지 않은 경우 어떻게 그것을 역전시킬 수 있습니까? –

+0

명백한 한계로 보지 않습니다. 확신 할 수는 없지만 결과 ID를 구체화하지 않고 쿼리에서 "Order by Id DESC"를 푸시 할 수 있습니다. – JohnMetta

답변

1

IQueryable<T>IEnumerable<T>이므로, AsEnumerable은 중복됩니다. 그러나 AsEnumerable을 사용하면 매우 귀찮은 "기능"이 될 컬렉션을로드하지 않습니다. 분명히 Reverse는 모든 것을 필요로 할 것입니다. Mono는 List<T>과 반대로 생성되는 간단한 iterator-generator를 사용하여 Enumerable.Reverse을 구현합니다.

AsEnumerable의 유일한 실제 목적은 IEnumerable 명시 적 인터페이스 구현을 사용하는 것입니다.

+0

예, AsEnumerable은 모든 것을 메모리에로드하지 않습니다. 실제로 유형을 변경하는 것만 제외하고는 아무 일도하지 않습니다. –

+0

하지만 Enumerable의 where 연산자는 데이터베이스 액세스에 대해 전혀 모르는 상태이므로 쿼리를 수행하기 위해 메모리에 개체가 필요합니다. Where 연산자 (AsEnumerable 호출 후)는 데이터베이스에서 모든 레코드를로드하여 필터링 할 수 있도록합니다. –

4

AsEnumerable 식의 컴파일 타임 유형을 변경하는 것 외에는 아무 것도 수행하지 않습니다.

그것은이 다음과 같이 구현 것 :

public static IEnumerable<T> AsEnumerable<T>(this IEnumerable<T> source) 
{ 
    return source; 
} 

그것도 무효 확인하지 않습니다!

유일하게 요점은 컴파일 타임 형식을 변경하여 나머지 쿼리가 쿼리 가능 대신 확장 가능한 확장 메서드로 실행되도록하는 것입니다. 그것은 캐스트와 같습니다. 단, 캐스트가 쿼리 중간에 불편할 수 있으며, 익명 형식의 경우 캐스팅 할 수 없습니다.

실제로 쿼리의 "원본"이 열거 될 때 수행되는 작업과 관련이 있습니다. 이 소스는 결과를 반환하기 전에 모든 것을 메모리에로드합니까? 아니면 스트림합니까? IIRC, LINQ to SQL은 실제로 모든 것을 메모리에로드합니다.하지만 잘못 될 수 있습니다. 물론 Reverse은 어쨌든 어떤 것도 버퍼링 할 것입니다.하지만 메모리를 두 배로 사용한다는 의미는 아닙니다. 대부분의 경우 버퍼가됨을 의미합니다. 참조을 개체로; 각 오브젝트의 새로운 사본을 작성하지는 않습니다.

+0

그리고 질문의 두 번째 부분에 대답하기 위해 실제로 모든 레코드를로드하는 것은 'Reverse' 메서드입니다. –

+0

이렇게하면 db.Countries.AsEnumerable(). Reverse(). 여기서 (c => c.국가 ID == ""I ") 실행될 쿼리는 데이터베이스에서 메모리로 모든 레코드를 가져온 다음 Enumerable의 역방향 및 Where 연산자가 작동합니다. 개체가 쿼리를 위해 메모리에 있어야하므로 매우 비효율적입니다. 내가 맞습니까? –

+0

@Akshay : SQL에서 그렇게하는 것이 낫습니다. 버려 질 수있는 데이터로드를 전송할 필요가 없습니다. 나는 값을 데이터베이스에서 다시 가져 오는 순서를 바꾸기보다는 순서를 사용하는 것이 좋습니다. –

관련 문제