Programing

IQueryable, List, IEnumerator의 차이점은 무엇입니까?

lottogame 2020. 12. 1. 07:33
반응형

IQueryable, List, IEnumerator의 차이점은 무엇입니까?


IQueryable, List, IEnumerator의 차이점이 무엇이며 언제 각각을 사용해야하는지 궁금합니다.

예를 들어 Linq를 SQL로 사용할 때 다음과 같은 작업을 수행합니다.

public List<User> GetUsers()
{
   return db.User.where(/* some query here */).ToList();
}

이제 대신 IQueryable을 사용해야하는지 궁금합니다. 목록을 통해 사용하는 이점이 확실하지 않습니다.


IQueryable<T>쿼리 공급자 (예 : LINQ to SQL 또는 Entity Framework와 같은 ORM)가 쿼리에 포함 된 식을 사용하여 요청을 다른 형식으로 변환 할 수 있도록하기위한 것입니다. 즉, LINQ-to-SQL은 사용자가 만드는 비교와 함께 사용중인 엔터티의 속성을 확인하고 실제로 동일한 요청을 표현하는 SQL 문을 만듭니다.

IEnumerable<T>IQueryable<T>(모든 인스턴스가 IQueryable<T>구현 되지만 )보다 일반적이며 IEnumerable<T>시퀀스 만 정의합니다. 그러나 Enumerable해당 인터페이스에서 일부 쿼리 유형 연산자를 정의하고 일반 코드를 사용하여 이러한 조건을 평가 하는 클래스 내에서 사용할 수있는 확장 메서드가 있습니다 .

List<T>는 출력 형식 일 IEnumerable<T>뿐이며을 구현하는 동안 쿼리와 직접 관련이 없습니다.

즉,를 사용할 때 다른 것으로 번역 IQueryable<T>되는 표현식정의하는 것입니다. 비록 당신이 코드를 작성하고 있지만, 그 코드 가져 결코 실행되지 , 그것은 단지됩니다 검사 및 실제 SQL 쿼리와 같은 다른 무언가로 돌았 다. 이로 인해 이러한 표현에서는 특정 사항 만 유효합니다. 예를 들어 LINQ-to-SQL은 호출을 SQL 문으로 바꾸는 방법을 모르기 때문에 이러한 식 내에서 정의하는 일반 함수를 호출 할 수 없습니다. 이러한 제한의 대부분은 불행히도 런타임에만 평가됩니다.

IEnumerable<T>쿼리에 사용할 때 LINQ-to-Objects를 사용합니다. 즉, 쿼리를 평가하거나 결과를 변환하는 데 사용되는 실제 코드를 작성하고 있으므로 일반적으로 수행 할 수있는 작업에 제한이 없습니다. . 이 표현식 내에서 자유롭게 다른 함수를 호출 할 수 있습니다.

LINQ to SQL 사용

위의 구분과 함께 진행하면서 이것이 실제로 어떻게 작동하는지 염두에 두는 것도 중요합니다. LINQ to SQL의 데이터 컨텍스트 클래스에 대한 쿼리를 작성하면 IQueryable<T>. 그 자체 에 대해IQueryable<T> 무엇을하든 SQL로 전환되므로 필터링 및 변환이 서버에서 수행됩니다. 이에 대해 무엇 이건 int로서IEnumerable<T> , 응용 프로그램 수준에서 수행됩니다. 때로는 이것이 바람직하지만 (예를 들어 클라이언트 측 코드를 사용해야하는 경우), 대부분의 경우 이는 의도하지 않은 것입니다.

예를 들어 테이블을 Customers나타내는 속성 이있는 컨텍스트가 Customer있고 각 고객에게 CustomerId열이있는 경우이 쿼리를 수행하는 두 가지 방법을 살펴 보겠습니다.

var query = (from c in db.Customers where c.CustomerId == 5 select c).First();

그러면 데이터베이스에 5와 같은 Customer레코드 를 쿼리하는 SQL이 생성됩니다 CustomerId.

select CustomerId, FirstName, LastName from Customer where CustomerId = 5

우리가 설정 한 경우 이제 어떤 일이 발생 CustomersIEnumerable<Customer>사용하여 AsEnumerable()확장 방법을?

var query = (from c in db.Customers.AsEnumerable() where c.CustomerId == 5 select c).First();

이 간단한 변경은 심각한 결과를 가져옵니다. 우리가 회전하고 있기 때문에 Customers으로 IEnumerable<Customer>,이 전체 테이블에 다시 나타납니다와 (클라이언트 측에서 그것을 필터링 아니라, 엄격하게 테이블의 모든 행을 다시 가져올 것이 말하기 는 기준에 맞는 하나를 만날 때까지 ,하지만 포인트가있다 같은).

ToList ()

지금까지 우리는 IQueryable및에 대해서만 이야기했습니다 IEnumerable. 이는 유사하고 보완적인 인터페이스이기 때문입니다. 두 경우 모두 쿼리를 정의 합니다 . 즉, 데이터를 찾을 위치 , 적용 필터 및 반환 데이터를 정의합니다. 둘 다 쿼리입니다.

query = from c in db.Customers where c.CustomerId == 5 select c;
query = from c in db.Customers.AsEnumerable() where c.CustomerId == 5 select c;

앞서 이야기 한 것처럼 첫 번째 쿼리는를 사용 IQueryable하고 두 번째 쿼리는 IEnumerable. 그러나 두 경우 모두 이것은 단지 쿼리 일뿐 입니다. 쿼리를 정의하는 것은 실제로 데이터 소스에 대해 아무 작업도 수행하지 않습니다. 쿼리는 코드가 목록을 반복하기 시작할 때 실제로 실행됩니다. 이것은 여러 가지 방법으로 발생할 수 있습니다. foreach루프 호출 ToList()

쿼리는 처음에 그리고 반복 마다 실행 됩니다. 전화 할 것 인 경우 ToList()query두 번, 당신은 완전히 다른 오브젝트와 두 개의리스트로 끝날 것입니다. 동일한 데이터를 포함 할 수 있지만 서로 다른 참조입니다.

댓글 후 수정

클라이언트 측에서 작업을 완료 한 시점과 서버 측에서 처리 한 시점의 차이를 명확히하고 싶습니다. 당신이 참조하는 경우 IQueryable<T>가 AS를 IEnumerable<T>, 단지 질의 완료 그것이이야 IEnumerable<T>완료 클라이언트 측 될 것입니다. 예를 들어이 테이블과 LINQ-to-SQL 컨텍스트가 있다고 가정합니다.

Customer
-----------
CustomerId
FirstName
LastName

먼저 FirstName. 이렇게하면 IQueryable<Customer>다음 이 생성됩니다 .

var query = from c in db.Customers where c.FirstName.StartsWith("Ad") select c;

Now I pass that query to a function that takes an IEnumerable<Customer> and does some filtering based on LastName:

public void DoStuff(IEnumerable<Customer> customers)
{
    foreach(var cust in from c in customers where c.LastName.StartsWith("Ro"))
    {
        Console.WriteLine(cust.CustomerId);
    }
}

We've done a second query here, but it's being done on an IEnumerable<Customer>. What's going to happen here is that the first query will be evaluated, running this SQL:

select CustomerId, FirstName, LastName from Customer where FirstName like 'Ad%'

So we're going to bring back everyone who's FirstName starts with "Ad". Note that there's nothing in here about LastName. That's because it's being filtered out client-side.

Once it brings back these results, the program will then iterate over the results and deliver only the records whose LastName starts with "Ro". The downside to this is that we brought back data--namely, all rows whose LastName doesn't start with "Ro"--that could have been filtered out on the server.


IQueryable<T>: abstracts database access, supports lazy evaluation of queries
List<T>: a collection of entries. No support of lazy evaluation
IEnumerator<T>: supplies the ability of iterating over and IEnumerable<T> (which both IQueryable<T> and List<T> are)

The problem with that code is quite simple - it always executes the query when it is called. If you were to return db.User.Where(...) instead (which is an IQueryable<T>), you'd hold the evaluation of the query until it is actually needed (iterated over). Also, if the user of that method would need to specify further predicates, those also be executed in the database, which makes it way faster.


Use iList or List<item> when you want a strongly typed collection of a some entity.

And Use Iqueryable and Ienumurator when you want to get dumb data as an collection of objects, it will come back as a loose type collection and no restrictions applied.

I would rather use List<type> because using a list wrap and cast in a strongly type collection my result set.

Also, using a list will give you the ability to add, sort and convert layer into Array, Ienumurator or as Queryable.

참고URL : https://stackoverflow.com/questions/4844660/differences-between-iqueryable-list-ienumerator

반응형