2014-12-09 1 views
1

부모 카테고리를 검색하고자하는 자체 참조 Category 클래스가 있고 적어도 하나 이상의 하위 카테고리가 있고 적어도 하나 이상의 자식이 있다면 활동 (ICollection<Activity>)을 컬렉션에 추가하십시오.컬렉션이있는 자식의 부모/자식을 검색 한 Linq 질의

최소한 1 개 이상의 활동이있는 하위 카테고리가있는 경우에만 반환해야하므로 어린이의 어린이에게도 해당됩니다.

하나 이상의 활동이있는 하위 카테고리가없는 경우 Category이 아니고이 반환되어야합니다.

쿼리는 부모 CategoryCategoryId이 아닌 실제 Category 개체로 반환해야합니다. 가능한가요?

public class Category 
{ 
    public int CategoryId { get; set; } 
    public string Name { get; set; } 
    public int? ParentId { get; set; } 
    public virtual Category Parent { get; set; } 

    public virtual ICollection<Category> Children { get; set; } 
    public virtual ICollection<Activity> Activities { get; set; } 
} 

UPDATE 1

부분적으로 작동하는 쿼리

var categories = _db.Categories 
     .Where(x => x.Parent != null && x.Activities.Count > 0) 
     .GroupBy(x => x.ParentId) 
     .Select(g => new { Parent = g.Key, Children = g.ToList() }).ToList(); 
+1

시도한 쿼리는 어디에 있습니까? – Mivaweb

+0

'ParentId'를 저장하는 특별한 이유가 있습니까? 'Parent.CategoryId'에서 이걸 얻을 수 없을까요? –

+0

@RufusL 이것은 EF에서 전형적인 것이므로 참조 된 엔티티를 실제로 제거하지 않고 행을 하나의 엔티티로 가져올 수 있습니다. 부모 객체에는 연결되지 않지만 부모 객체에는 연결되지 않는 ID를 얻습니다. – juharr

답변

1

당신이 만들 찾고있는 쿼리가 다소 복잡하기 때문에 이제 조금 작은 시작하자. 아래에서 위로 쿼리를 작성하겠습니다. 첫째, 적어도 하나 이상의 활동이있는 하위 카테고리가없는 카테고리를 제거하고 싶습니다. Predicate을 포함해야하는 사람들에게 true, 단일 레벨에서 제외해야 할 사람들에게 false을 반환하도록합시다. 우리는 이것을 두 단계로 수행 할 것입니다. 먼저, 활동이 범주에 대한 true를 반환하는 술어 만들어 보자 :

Predicate<Category> hasChildWithActivities = 
    parentCat => parentCat.Children.Any(hasActivities); 


:

Predicate<Category> hasActivities = cat => cat.Activities.Any(); 

둘째,의 활동이 자식 범주와 그 범주에 대한 true을 반환하는 Predicate을 만들어 보자 이제 지정된 Category의 자손을 필터링하는 필터 쿼리를 작성해 보겠습니다. 이를 위해, 우리는 부모 Category 소요 Func을 만들 것입니다, 논리를 수행하고 Category 업데이트 반환 : 당신 OP에서

Func<Category, Category> getFilteredCategory = delegate(Category parentCat) 
{ 
    parentCat.Children = parentCat.Children 
     .Where(hasChildWithActivities) 
     .Select(getFilteredCategory); 

    return parentCat; 
}; 


:이 동등한 것으로

Func<Category, Category> getFilteredCategory = 
    parentCat => 
    { 
     parentCat.Children = parentCat.Children 
      .Where(hasChildWithActivities) 
      .Select(getFilteredCategory); 

     return parentCat; 
    }); 

주 , 부모님도 걸러 내고 싶다고 말씀하셨습니다. 상위 레벨까지 이동하여이 쿼리를 실행하거나 "조인"또는보다 복잡한 "select"문으로 별도의 쿼리를 작성하여 부모에게 동일한 로직을 사용할 수 있습니다. IMHO, 후자는 아마도 지저분 할 것입니다. 그리고 나는 그것에 반대 할 것입니다. 논리를 부모 노드에도 적용해야하는 경우 먼저 트리를 탐색합니다. 어느 쪽이든, 이것은 당신에게 좋은 시작을 제공해야합니다.


당신이 어떤 질문이 있으면 알려주세요. 행운과 행복을위한 코딩! :)