2012-01-23 7 views
9

저는 Microsoft의 Entity Framework를 ORM으로 사용하고 있으며 다음 문제를 해결하는 방법을 궁금합니다. 오늘 Product.StartDate이 (가) Products 컬렉션에서 Product 개체를 얻고 싶습니다. (이 모든 문제의 단순화 된 버전입니다.)EntityFramework의 LINQ 파서가 외부 정의 된 조건자를 다르게 처리하는 이유는 무엇입니까?

내가 현재 사용

var query = dbContext.Products.Where(p => p.StartDate > DateTime.Now); 

을이이 쿼리에 대한 예를 들어 ToList() 사용 후, 실행되면 작동하고 생성 된 SQL 효율적입니다 :

SELECT * FROM Product WHERE StartDate > (GetDate()); 

그러나, 나는 더 나은 유지 보수하는 기능에 술어를 이동하려는, 그래서 나는이 시도 :

private Func<Product, bool> GetFilter() 
{ 
    Func<Product, bool> filter = p => p.StartDate > DateTime.Now; 
    return filter; 
} 
var query = dbContext.Products.Where(GetFilter()); 

SELECT * FROM Product; 

필터는 그것을 만드는 클라이언트에 SQL 서버에서 이동 :

이 또한 같은 Product 집합을 반환하지만 같은 SQL 작성이 시간에 유사하는 한보기의 코드 포인트에서 작동 효율성이 훨씬 떨어집니다.

그래서 제 질문은 다음과 같습니다

  • 왜 이런 일이 왜 LINQ 파서는 너무 다른이 두 형식을 처리 않습니다입니까?
  • 필터를 별도로 가지고 있지만 서버에서 실행되도록하려면 어떻게해야합니까?

답변

4

Func을 반환하지만 SQL에 조건자를 삽입하려면 LINQ에 표현식 트리가 필요합니다. 메서드의 반환 유형 (물론 지역 변수)을 Expression<Func<Product, bool>>으로 변경하면 작동합니다.

8

의도 한대로 작동하려면 Expression<Func<Product, bool>>을 사용해야합니다. Func<Product, bool>이라는 일반 문자는 LINQ가 SQL이 아닌 프로그램에서 MSIL로 Where을 실행하도록합니다. 그래서 SQL이 전체 테이블을 끌어 당기는 것입니다. 그런 다음 .NET 코드가 전체 테이블에서 조건자를 실행하고있는 것입니다.

+0

+1 바로 저를 때려주십시오. –

+0

@Dommer 하하! 나는 전형적으로 아주 좋은 "빠른 끌기"가 아니다! –

+1

감사합니다. –

2

두 번째 경우에 filter func이 임의로 LINQ to EF로 변환되어 SQL로 필터링 할 수 없으므로 클라이언트 측에서 필터링해야합니다.

+0

동의하지만 첫 번째 예제의 표현이 무엇이든 될 수 있으므로 전체 답이 될 수는 없습니다. GetFilter 함수가 인라인 술어와 동시에 검사 된 경우 아무런 문제가 없습니다. 이것은 실행 순서가 다르다는 것을 의미합니까? –