IQueryable <T>와 IEnumerable <T>의 차이점은 무엇입니까?


답변:


258

우선 , 인터페이스를 확장 하므로 "plain" 으로 수행 할 수있는 모든 작업은 .IQueryable<T> IEnumerable<T>IEnumerable<T>IQueryable<T>

IEnumerable<T>다만이 GetEnumerator()반환 방법 Enumerator<T>당신이 호출 할 수있는 MoveNext()일련의 반복하는 방법을 T를 .

어떤 IQueryable<T>이있다 IEnumerable<T> 하지 않습니다 특히-한 두 가지 속성은있는 포인트 쿼리 제공자 (예를 들어, SQL 공급자에 대한 LINQ)과 또 다른 하나를 가리키는 쿼리 식 표현 IQueryable<T>될 수있는 런타임에 이동 추상 구문 트리로 객체를 주어진 쿼리 공급자가 이해합니다 (대부분의 경우 예외가 발생하지 않고 LINQ to SQL 공급자에게 LINQ to SQL 식을 제공 할 수 없음).

표현식은 단순히 오브젝트 자체의 상수 표현식이거나 구성된 쿼리 연산자 및 피연산자 세트의 더 복잡한 트리 일 수 있습니다. 쿼리 공급자 IQueryProvider.Execute()또는 IQueryProvider.CreateQuery()메서드가 전달 된 Expression 과 함께 호출 된 다음 쿼리 결과 또는 다른 결과 IQueryable가 각각 반환됩니다.


8
AsQueryable을 사용하면 어떤 이점이 있습니까?
Jordan

6
유일한 이점은 편의성입니다. AsQueryable()열거 형을 쿼리 가능 객체로 캐스팅하고 IQueryable인터페이스를 구현하면 ConstantExpression반환 EnumerableQuery합니다. 그렇지 않으면 반환 된 객체 에서 참조되는로 래핑됩니다 .
Mark Cidade



@JenonD 링크는 여기 죽은입니다 waybackmachine입니다 : web.archive.org/web/20160904162931/http://www.dotnet-tricks.com/...
majjam

201

가장 큰 차이점은 델리게이트 대신 객체 를 IQueryable<T>가져 오는 LINQ 연산자 Expression는 예를 들어 조건 자 또는 값 선택기와 같이받는 사용자 지정 쿼리 논리가 메서드에 대한 델리게이트가 아닌 식 트리의 형식임을 의미합니다.

  • IEnumerable<T> 메모리 내에서 반복되는 시퀀스 작업에 유용하지만
  • IQueryable<T> 데이터베이스 또는 웹 서비스와 같은 원격 데이터 소스와 같은 메모리 부족을 허용합니다.

쿼리 실행 :

  • 쿼리 실행이 "in process"에서 수행되는 경우 일반적으로 필요한 것은 쿼리의 각 부분을 실행하는 코드 (코드)입니다.

  • 실행이 프로세스 외부에서 수행 되는 경우 LINQ 공급자가 LDAP 쿼리이든 관계없이 LINQ 공급자가 메모리 부족 실행에 적합한 형식으로 변환 할 수 있도록 쿼리 논리를 데이터로 나타내야합니다. SQL 또는 무엇이든.

더 :

http://www.codeproject.com/KB/cs/646361/WhatHowWhere.jpg


14
메모리 부족 작업에 대한 언급이 마음에 듭니다. 실제 사용상의 차이를 분명히합니다.
Ishmael Smyrnow 2016 년

2
IEnumerable <T> Where 메서드처럼 대리자를 매개 변수로 사용하는 대신 IQueryable <T>는 Expression <TDelegate> 매개 변수를 사용합니다. 우리는 코드를 IQueryable <T>에 전달하지 않고 LINQ 공급자가 분석 할 식 트리 (데이터로 코드)를 전달합니다. C # 3.0 및 LINQ
Lu55

무언가는 어떤 이유로 게시물 본문에 렌더링되지 않는, 이미지 링크와 함께입니다 codeproject.com/KB/cs/646361/WhatHowWhere.jpg
jbooker

@joey 그러나, 나는이 답변에서 그 이미지를 잘 볼 수 있습니다 : i.stack.imgur.com/2DAqv.jpg
VonC

190

이것은 YouTube 의 멋진 비디오 로서 이러한 인터페이스가 어떻게 다른지 보여줍니다.

아래는 그것에 대한 긴 해답입니다.

기억해야 할 첫 번째 중요한 점은 IQueryable인터페이스가에서 상속 받으 IEnumerable므로 무엇이든 IEnumerable할 수있는 IQueryable것입니다.

여기에 이미지 설명을 입력하십시오

많은 차이점이 있지만 가장 큰 차이점을 만드는 하나의 큰 차이점에 대해 논의하겠습니다. IEnumerableinterface는 LINQ또는 Entity 프레임 워크를 사용하여 컬렉션을로드 하고 컬렉션에 필터를 적용하려는 경우에 유용합니다 .

IEnumerable엔티티 프레임 워크와 함께 사용되는 아래 간단한 코드를 고려하십시오 . 사용하고 Where그 기록을 얻기 위해 필터 EmpId입니다 2.

EmpEntities ent = new EmpEntities();
IEnumerable<Employee> emp = ent.Employees; 
IEnumerable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();

여기서 필터는 IEnumerable코드가 있는 클라이언트 측에서 실행됩니다 . 즉, 모든 데이터는 데이터베이스에서 가져온 다음 클라이언트에서 EmpIdis로 스캔하고 레코드를 가져옵니다 2.

여기에 이미지 설명을 입력하십시오

그러나 이제 아래 코드가로 변경 IEnumerable되었습니다 IQueryable. 서버 측에서 SQL 쿼리를 작성하고 필요한 데이터 만 클라이언트 측으로 전송합니다.

EmpEntities ent = new EmpEntities();
IQueryable<Employee> emp = ent.Employees;
IQueryable<Employee> temp =  emp.Where(x => x.Empid == 2).ToList<Employee>();

여기에 이미지 설명을 입력하십시오

따라서 필터 로직이 실행되는 위치 IQueryable와 차이 IEnumerable가 있습니다. 하나는 클라이언트 쪽에서 실행되고 다른 하나는 데이터베이스에서 실행됩니다.

따라서 메모리 내 데이터 수집 IEnumerable만 사용하는 것이 좋지만 데이터베이스와 연결된 데이터 수집을 쿼리하려면`IQueryable이 네트워크 트래픽을 줄이고 SQL 언어의 힘을 사용하므로 더 나은 선택입니다.


안녕하세요, 훌륭한 설명 감사합니다. "메모리 부족"데이터에 대해 IQueryable이 더 나은 선택 인 이유를 이해하지만 IEnumerable이 "메모리 내"데이터에 더 적합한 이유를 이해하려고 애 쓰고 있습니까? 나는 여전히 데이터를 얻고 필터를 적용하는 것보다 필터링 된 데이터를 얻는 것이 낫다고 생각합니다.
Imad

"메모리 내"일 때는 실제로 중요하지 않습니다. 데이터는 이미 메모리에 있으며, 필터링되는 정확한 시간은 중요하지 않습니다.
Roni Axelrad 2016 년

@Imad 예를 들어, 엔티티 DateTimeOffset을 DateTime으로 변환하여 데이터를 투영하는 것은 IQueryable 또는 EntityFunctions를 사용하여 수행 할 수 없습니다. 가장 좋은 방법은 엔티티 객체를 AsEnumerable ()하고 DateTime을 포함하는 뷰 모델로 Select ()하는 것입니다. 이 프로세스는 메모리 내 기능을 사용합니다.
Jeff Li

57

IEnumerable : IEnumerable은 메모리 내 컬렉션 (또는 로컬 쿼리) 작업에 가장 적합합니다. IEnumerable은 항목간에 이동하지 않으며 앞으로 만 수집됩니다.

IQueryable : IQueryable은 데이터베이스 또는 웹 서비스 (또는 원격 쿼리)와 같은 원격 데이터 소스에 가장 적합합니다. IQueryable은 다양한 흥미로운 지연된 실행 시나리오 (페이징 및 컴포지션 기반 쿼리 등)를 가능하게하는 매우 강력한 기능입니다.

따라서 메모리 내 컬렉션을 단순히 반복해야하는 경우 IEnumerable을 사용하십시오. Dataset 및 기타 데이터 소스와 같은 컬렉션을 조작해야하는 경우 IQueryable을 사용하십시오.


3
IEnumerable이 지연된 실행을 사용하지 않습니까?
Ian Warburton

3
지연된 실행은 IEnumerable과 IQueryable에서 모두 사용할 수 있습니다. 더 흥미로운 정보는 여기에서 찾을 수 있습니다 : stackoverflow.com/questions/2876616/…
Ignacio Hagopian

18

간단히 말하면 다른 주요 차이점은 IEnumerable이 서버 측에서 선택 쿼리를 실행하고 클라이언트에서 데이터를 메모리에로드 한 다음 데이터를 필터링하는 반면 IQueryable은 모든 필터를 사용하여 서버 측에서 select 쿼리를 실행한다는 것입니다.


17

실제로 LINQ-to-SQL과 같은 ORM을 사용하는 경우

  • IQueryable을 작성하면 조회가 sql로 변환되어 데이터베이스 서버에서 실행될 수 있습니다.
  • IEnumerable을 만들면 쿼리를 실행하기 전에 모든 행이 개체로 메모리로 가져옵니다.

두 경우 모두 당신이 전화하지 않는 경우 ToList()또는 ToArray()다음 쿼리가 사용될 때마다 실행됩니다, 그래서 말하자면, 당신은이 IQueryable<T>당신은 다음 쿼리는 데이터베이스의 4 배에 대해 실행됩니다 그것에서 4 목록 상자를 입력합니다.

또한 쿼리를 확장하는 경우 :

q.Where(x.name = "a").ToList()

그런 다음 IQueryable을 사용하면 생성 된 SQL에 "where name ="a "가 포함되지만 IEnumerable을 사용하면 데이터베이스에서 더 많은 역할을 가져오고 x.name ="a "검사가 .NET에 의해 수행됩니다.


10

IEnumerable은 컬렉션을 참조하지만 IQueryable은 쿼리 일 뿐이며 Expression Tree 내에서 생성됩니다.이 쿼리를 실행하여 데이터베이스에서 데이터를 가져옵니다.


8

언급 한 작은 테스트 도움이 될 아래에는 차이의 한 측면을 이해 IQueryable<T>하고를 IEnumerable<T>. 다른 사람의 게시물에 수정 사항을 추가하려고하는 게시물 에서이 답변을 재현 했습니다.

DB에서 다음 구조를 만들었습니다 (DDL 스크립트).

CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)

레코드 삽입 스크립트 (DML 스크립트)는 다음과 같습니다.

INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(1, 20)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(2, 30)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(3, 40)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(4, 50)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(5, 60)
GO

이제 목표는 Employee데이터베이스의 테이블에서 상위 2 개의 레코드를 가져 오는 것이 었습니다 . Employee데이터베이스의 테이블을 가리키는 콘솔 응용 프로그램에 ADO.NET 엔터티 데이터 모델 항목을 추가하고 LINQ 쿼리 작성을 시작했습니다.

IQueryable 경로 코드 :

using (var efContext = new EfTestEntities())
{
    IQueryable<int> employees = from e in efContext.Employees  select e.Salary;
    employees = employees.Take(2);

    foreach (var item in employees)
    {
        Console.WriteLine(item);
    }
}

이 프로그램을 실행하기 시작했을 때 SQL Server 인스턴스에서 SQL 쿼리 프로파일 러 세션도 시작했으며 다음은 실행 요약입니다.

  1. 실행 된 총 쿼리 수 : 1
  2. 쿼리 텍스트 : SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]

그것은 그 그냥 IQueryable적용하는 스마트 충분 Top (2)가 와이어를 통해 5 개 기록의 2 아웃을 제공하므로 데이터베이스 서버 측 자체에 절은. 클라이언트 컴퓨터 측에서는 추가 메모리 내 필터링이 전혀 필요하지 않습니다.

IEnumerable 경로 코드 :

using (var efContext = new EfTestEntities())
{
    IEnumerable<int> employees = from e in efContext.Employees  select e.Salary;
    employees = employees.Take(2);

    foreach (var item in employees)
    {
        Console.WriteLine(item);
    }
}

이 경우 실행 요약 :

  1. 실행 된 총 쿼리 수 : 1
  2. SQL 프로파일 러에서 캡처 된 쿼리 텍스트 : SELECT [Extent1].[Salary] AS [Salary] FROM [dbo].[Employee] AS [Extent1]

이제 IEnumerable5 개의 레코드가 모두 Salary테이블에 표시되고 클라이언트 컴퓨터에서 인 메모리 필터링을 수행하여 상위 2 개의 레코드를 얻습니다. 따라서 더 많은 데이터 (이 경우 3 개의 추가 레코드)가 불필요하게 전송되었습니다.


7

다음은 비슷한 주제에 대한 글입니다. (아니오, 나는 보통 나 자신을 인용하지 않지만 이것들은 아주 좋은 기사입니다.)

"이 기사는 도움이됩니다 : LINQ-to-SQL에서 IQueryable과 IEnumerable .

'MSDN 문서에 따르면 IQueryable에 대한 호출은 대신 내부 식 트리를 작성하여 작동합니다. "IQueryable (Of T)을 확장하는 이러한 메서드는 쿼리를 직접 수행하지 않습니다. 대신, 해당 기능은 누적 쿼리를 나타내는 식 트리 인 Expression 개체를 작성하는 것입니다." '

식 트리는 C # 및 .NET 플랫폼에서 매우 중요한 구성입니다. (일반적으로 중요하지만 C #을 사용하면 매우 유용합니다.) 차이점을 더 잘 이해하려면 공식 C # 5.0 사양의 표현식명령문 의 차이점에 대해 읽어 보는 것이 좋습니다 . 람다 미적분학으로 분기되는 고급 이론적 개념의 경우 표현식을 사용하면 메소드를 일류 객체로 지원할 수 있습니다. IQueryable과 IEnumerable의 차이점은이 지점을 중심으로합니다. IQueryable은 표현 트리를 구축하지만 IEnumerable은 Microsoft의 비밀 실험실에서 일하지 않는 사람들에게는 적어도 일반적인 용어는 아닙니다.

여기에 푸시 대 풀 관점의 차이점을 자세히 설명하는 또 다른 유용한 기사가 있습니다. "푸시"와 "풀"은 데이터 흐름의 방향을 나타냅니다. .NET 및 C #에 대한 반응성 프로그래밍 기법

다음은 명령문 람다와 식 람다의 차이점을 자세히 설명하고 C # 대리자, 식 트리 및 람다 문 대 람다 식 다시 방문 의 식 트레스 개념에 대해 자세히 설명하는 매우 유용한 기사입니다 . "


6

데이터베이스에서 검색된 데이터를 사용 IEnumerable하고 IQueryable조작합니다. IQueryable에서 상속 IEnumerable되므로 IQueryable모든 IEnumerable기능 이 포함됩니다 . 주요 차이점 IQueryableIEnumerableIQueryable반면 필터를 실행하는 질의 IEnumerable질의 1 및 다음 조건에 기초하여 데이터를 필터링 실행한다.

아래에서 더 자세한 차별화를 찾으십시오.

IEnumerable

  1. IEnumerableSystem.Collections네임 스페이스에 존재
  2. IEnumerable 서버 측에서 선택 쿼리를 실행하고 클라이언트 측에서 메모리에 데이터를로드 한 다음 데이터를 필터링
  3. IEnumerable List, Array와 같은 메모리 내 컬렉션에서 데이터를 쿼리하는 데 적합합니다.
  4. IEnumerable LINQ to Object 및 LINQ to XML 쿼리에 유용

iQueryable

  1. IQueryableSystem.Linq네임 스페이스에 존재
  2. IQueryable 모든 필터를 사용하여 서버 측에서 '선택 쿼리'를 실행합니다.
  3. IQueryable 원격 메모리 (예 : 원격 데이터베이스, 서비스) 컬렉션에서 데이터를 쿼리하는 데 적합합니다.
  4. IQueryable LINQ to SQL 쿼리에 유용

따라서 IEnumerable일반적으로 메모리 내 컬렉션 IQueryable을 처리하는 데 사용되는 반면 컬렉션을 조작하는 데 일반적으로 사용됩니다.



2

IQueryable은 데이터베이스의 필요량에 관계없이 IEnumerable이 모든 데이터를 가져 오는 데이터베이스에서 필요한 데이터 만 가져 오기 때문에 데이터베이스에서 대량의 데이터를 처리하는 경우 IEnumerable보다 빠릅니다.


0

ienumerable : 데이터 연결없이 inprocess 메모리를 처리하려고 할 때 iqueryable : SQL 서버, 즉 데이터 연결 ilist를 처리 할 때 : 객체 추가, 객체 삭제 등의 작업

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.