[Effective C#] 아이템 42: IEnumerable 데이터 소스와 IQueryable 데이터 소스를 구분하라
C# 카테고리의 다른 글
IEnumerable
하지만 항상 가능한 것은 아니며, 동작 방식과 성능에서 큰 차이가 난다.
아이템 38에서 LINQ to SQL (IQueryable
// 첫 번째 예
var q =
from c in dbContext.Customers
where c.City == "London"
select c;
var finalAnswer = from c in q
orderby c.Name
select c;
// finalAnswer에 대한 순회 코드는 생략
// 두 번째 예
var q =
(from c in dbContext.Customers
where c.City == "London"
select c).AsEnumerable();
var finalAnswer = from c in q
orderby c.Name
select c;
// finalAnswer에 대한 순회 코드는 생략
첫 번째 예는 일반적인 LINQ to SQL 쿼리이고 IQueryable
두 번째 예는 첫 번째 쿼리문이 IEnumerable
아이템 37에서 살펴봤듯이 IQueryable
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의 쿼리는 AsEnumerable() 메서드로 데이터 컬렉션을 IEnumerable로 변환시켰다.
그래서 where 절의 isValidProduct(p) 메서드가 제대로 수행될 수 있다. (LINQ to Objects로 수행됨)
하지만 q2의 쿼리는 IQueryable
이렇게 IQueryable
반대로 AsQueryable() 메서드도 유용하게 쓰일 수 있는 경우가 있다.
public static IEnumerable<Product> ValidProducts(
this IEnumerable<Product> products) =>
from p in products.AsQueryable()
where p.ProductName.LastIndexOf('C') == 0
select p;
위 코드는 products가 IQueryable
그렇지 않은 경우에는 LINQ to Objects가 수행된다.
추가로 where 절에 쓰인 LastIndexOf(‘c’)는 LINQ to SQL 라이브러리를 통해 올바르게 해석 가능한 메서드이다.
댓글남기기