2011-12-16 2 views
2

질문 제목에 무엇을 쓸지 몰랐습니다. 내 견본이야. 나는 다음과 같이 바의 컬렉션을 가진 푸 클래스가 :Linq 활성 하위 엔티티 쿼리

public class Foo 
{ 
    public bool Active {get; set;} 
    public ICollection<Bar> Bars {get; set;} 
} 

public class Bar 
{ 
    public bool Active {get; set;} 
} 

당신이 FOOS과 바 모두 비활성 (Active = false)로 설정할 수 있습니다 볼 수 있듯이. 나는 활동적인 바를 가진 모든 활동적인 Foo를 반환 할 서비스 (RIA)를 쓰는 것을 그다지 좋아하지 않는다.
그래서 이것은 내가 지금까지 무엇을 가지고 :

public IQueryable<Foo> GetFoos() 
{ 
    return ObjectContext.Foos.Where(f => f.Active) 
          .Include("Bars"); 
} 

것은 위의 쿼리는 모든 단일 Bar와 모든 활성 Foo를 반환, 그래서 어떻게 활성 Bars을 포함합니까?

답변

1

Include 메서드는 LazyLoading의 일부입니다. 게으른로드는 모두 또는 아무것도 아니므로 EF에 일부 막대 만로드하도록 지시 할 수는 없습니다.

당신이해야 할 시도 할 수 있습니다 무엇, 그러나, 결과로 익명의 객체를 사용하는 것입니다 :

context.Foos 
.Where(f => f.Active) 
.Select(f => new { Foo = f, Bars = f.Bars.Where(b => b.IsActive }); 
+0

간단하면서도 효과적인 ... 대단히 감사합니다! – sebagomez

1

EF는 EF가 작동하도록 설계된 철학에 위배되기 때문에 쉽게 만들 수 없습니다. 각 Foo 엔터티의 Bars 컬렉션에 '활성'Bar 엔터티 만 포함되도록이 쿼리를 작성하는 것이 쉬운 경우 각 Foo 엔터티는 데이터베이스 상태의 정확한 모델이 아닙니다.

반면에 Foo 엔티티를 직접 검색하는 대신 프로젝션을 사용하여 쿼리를 작성하면 유연성이 향상됩니다.

var query = 
    from f in ObjectContext.Foos 
    where f.Active 
    select new { Foo = f, ActiveBars = f.Bars.Where(b=>b.Active)} 

이 시점에서 당신이 Foo 엔티티와 활성 Bar 엔티티를 다시 연결하는 foreach 루프 작성할 수 있습니다 : 예를 들어, 쿼리 이런 식으로 쓸 수

var results = query.ToList(); 

foreach (var r in results) 
    r.Foo.Bars = r.ActiveBars; 

을 그리고 마지막으로 결과를 반환하기 위해 LINQ 쿼리를 로컬로 실행하십시오.

return (from r in results select r.Foo).ToList(); 

그냥 방금 디스플레이 전용 시나리오에서 잘 작동 할 것이라고 설명했지만,이 방식으로 검색된 엔티티를 업데이트하려고 시도하는 것을 주저합니다.

관련 문제