2010-03-30 4 views
2

자주 사용되는 표현식을 linq 쿼리에서 분리하고 싶습니다. Entity Framework 4 및 LINQKit을 사용하고 있지만 올바른 방법으로 어떻게해야하는지 아직 모르겠습니다. 예를 들어 보겠습니다.Linq에서 외부 표현식을 EF4 (및 LINQKit)와 함께 사용하려면 어떻게해야합니까?

Article article = dataContainer.Articles.FirstOrDefault(a => a.Id == id); 

IEnumerable<Comment> comments = 
    (from c in article.Comments 
    where CommentExpressions.IsApproved.Invoke(c) 
    select c); 


public static class CommentExpressions 
{ 
    public static Expression<Func<Comment, bool>> IsApproved 
    { 
     get 
     { 
      return c => c.IsApproved; 
     } 
    } 
} 

물론 IsApproved 표현식은 훨씬 더 복잡합니다.

문제는 container.Comments의 LINQKit에서 .asExpandable()을 호출하지 않아 Invoke()가 작동하지 않지만 ObjectSet 대신 ICollection이기 때문에 호출 할 수 없다는 것입니다.

제 질문은 : 외부 표현식을 포함하고 싶을 때 항상 데이터 컨텍스트를 통과해야합니까? 아니면 가져온 개체에 어떻게 든 사용할 수 있습니까 (아티클)?

아이디어 또는 모범 사례? 대단히 감사합니다! 당신이 LinqKit이 술어 빌더를 사용하여 사용하는 것처럼 신

+0

"container.Comments"대신 "article.Comments"를 의미합니까, 샘플 코드의 4 번째 줄에 있습니까? – jeroenh

+0

오, 그래, 고마워, 고치다 – letmaik

답변

0

:

IEnumerable<Comment> comments = 
    article.Comments.Where(CommentExpressions.IsApproved).Select(c=>c); 

public static class CommentExpressions 
{ 
    public static Expression<Func<Module, bool>> IsApproved 
    { 
     get 
     { 
      var pred = PredicateBuilder.True<Module>(); 
      pred = pred.And(m => m.IsApproved); 
      return pred 
     } 
    } 
} 
+0

article.Comments.Where()가 Func 만 허용하고 표현식을 허용하지 않기 때문에 저에게 효과적이지 않습니다. (또한 오타가 있었지만 "Module, bool"이 아니지만 "Comment, bool", 죄송합니다.) – letmaik

1

문제는 EF 당신이 다른 방법으로 EF에 식을 접을 필요가 있으므로, 식을 호출 지원하지 않습니다이다.

기본적으로 요청하는 게시물을 Damien의 'Client-Side properties'게시물에서 확인해야합니다.

그리고 더 많은 배경 정보는 Invoke expressions with expressions EF can handle을 방문하고 바꾸는 방법을 보여주는 Colin Meek의 게시물을 확인하십시오.

희망이 내가 내 "문제"에 대한 답을 찾은 것 같아

알렉스

+0

흠 ... Damien의 게시물은 표현의 끝에 ".WithTranslations()"를 두는 것에 달려 있지만 다시는 그렇지 않습니다. 가능하다면 Article 개체를 가져온 후에 IQueryable을 얻지 못한다. article.Comments 및 .WithTranslations로 IQueryable에 대한 확장이 도움이되지 않습니다. 내가 뭔가를 간과했는지 말해봐. – letmaik

1

에게 도움이됩니다. 내 문제는 실제로 문제가 아니었지만 오히려 잘못된 사고 방식이었습니다.

this을 읽었을 때 잘못된 문제에 대한 해결책을 찾고 싶다는 사실이 나에게 분명했습니다. 설명해 드리겠습니다 ....

EF4와 함께 POCO 템플릿을 사용 중이며 지연로드가 여전히 활성화되어 있습니다. 이걸 사용하면 추가 쿼리를 보내지 않고 객체를 마술처럼 움직일 수 있습니다. 적어도 내 코드에는 표시되지 않았습니다. 물론 관계에 대한 각각의 액세스에 대해 질의가 보내졌고 EF 프로파일 러에서도이를 관찰했습니다. 물론 "최적의 방법"즉 "모든 행을 가져 와서 나중에 필터링"대신 "해당 SQL에서 where 조건 사용"을 사용하고 싶었습니다. 이러한 사고 방식은 조숙 한 최적화라고도합니다.

"게으른로드를 사용하지 않으면 어떻게 될 것입니까?" 간단합니다. 원하는 모든 데이터가 첫 번째 위치에서 가져오고 나면 해당 데이터를 조작하고 숨겨진 쿼리가없는 것입니다. 이런 식으로 보면 도메인 개체의 관계에 IQueryable 대신 ICollection을 사용하는 것이 좋습니다. 물론 ICollection에서 .Where() 호출에 Expression>을 사용할 수는 없지만 내부 Func < ..>을 사용해야합니다.

내 질문에 답하려면 표현식 <>은 저장소에 액세스하거나 POCO 개체가 인식하지 못하는 경우에만 사용해야합니다. 외부에서 사용해야하는 경우

IEnumerable<Comment> comments = 
    (from c in article.Comments 
    select c).Where(CommentExpressions.IsApproved.Compile()); 

을 그리고 정말 고성능에 대한 요구가있는 경우 그 저장소는 일치에 의해 그 기사에 속하는 모든 의견을 인출하도록 요청해야합니다 : Func을 컴파일 할 수있는 ICollection에에, 그들이 한 것은 그와 같은 객체 ID 및 WhereExpressions.IsApproved가 충족되었는지 확인하십시오. 뭐 그런 :

IEnumerable<Comment> comments = 
    (from c in dataContainer.ArticleComments 
    where c.ArticleId == article.Id 
    select c).Where(CommentExpressions.IsApproved); 

이제 조건 때문에 누락 된 .compile의 표현을 유지()와 SQL에서 사용 할 수있는 마지막.

나는 거의 이것에 만족합니다. 필자가 ".compile()"을 호출해야 할 필요성이 있으며 여전히 이해할 수없는 것은 하나의 Expression에서 .compile()을 호출하는 것 외에는 불가능한 다른 표현식을 사용하거나 구성해야한다는 것입니다. 왜냐하면 Expression 개체를 넣을 수없는 ICollection 만 다시 포함되기 때문입니다. 여기서 LINQKit을 사용하여 컴파일() 호출을 제거 할 수 있다고 가정합니다.

나는 올바른 방향으로 가고 싶습니다. 논리적 오류를 발견하거나 더 나은 방법을 생각하면 의견을 말해 주시면 답변을 업데이트 할 수 있습니다. 모두에게 감사드립니다!

관련 문제