방프리

21.09.18 Chapter4. LINQ 활용 (Item 42) 본문

C#/Effective C#

21.09.18 Chapter4. LINQ 활용 (Item 42)

방프리 2021. 9. 18. 17:37

Item 42 : IEnumerable<T> 데이터 소스와 IQueryable<T> 데이터 소스를 구분하라

 

IQueryable<T>와 IEnumerable<T>는 시퀸스 성향을 띈다는 점에서 비슷해보이지만, 실제로는 굉장히 많이 다르다.

IQueryable<T>는 특히 쿼리문 처리에서 뛰어난 성능을 보인다.

Enumerable<T> 확장 메서듣는 쿼리식 내의 람다 표현식과 함수 매개변수를 나타내기 위해서 델리게이트를 사용하고,

Queryable<T>는 동일한 함수라 하더라도 표현식 트리를 이용하여 처리한다. 

특히 로직의 처리를 Enumerable<T>는 해당 로직이 실행되는 곳에서 처리하고, Queryable<T>를 로직을 분석하여

실제 데이터가 있는 Database 혹은 장비에서 직접 처리 후 결과값을 가져오도록 한다. 

Queryable<T>는 이름에 맞게 쿼리식에 최적화 되어 있으므로 Enumerable<T>보다 더 다양한 기능을 제공한다.

하지만 조심해야할 부분은 있다.

private bool isValidProduct(Product p) =>
    p.ProductName.LastIndexOf('C') == 0;
    
var q1 = 
    from p in dbContext.Products.AsEnumerable()
    where isValidProduct(p)
    select p;

var q2 = 
    from p in dbContext.Products
    where isValidProduct(p)
    select p;

위의 코드에서 q1는 정상적으로 동작하지만, q2는 동작하지 않는다. 그 이유는 IQueryProvider에서 

예외를 발생시키기 때문이다.

성능보다 안전이 더 중요하다고 판단되면 Enumerable<T>의 사용을 추천한다. 하지만 거의 예외의 상황일 때에만 

사용될거라 생각한다.

List, Array 등 기본적인 시퀸스는 AsQueryable() 함수를 통해 IQueryable<T>로 변환이 가능하다. 

그렇기에 때에 따라서 맞춰서 사용하면 된다.

Comments