2011-10-11 117 views
1

我有一個簡單的對象列表「ProductGroups」(IQueryable)。 每個「ProductGroup」都有一個稱爲「Children」的ProductGroups集合,一個整數ParentId字段和一個布爾型「IsEnabled」字段。用LINQ過濾整個分層列表

public class ProductGroup 
{ 
    public int Id; 
    public int ParentId; 
    public ICollection<ProductGroup> Children; 
    public bool IsEnabled; 
} 

我希望能夠返回「IsEnabled」爲true的ProductGroups樹。

此刻,如果我做

ProductGroups.Where(x => x.IsEnabled) 

這將返回功能的產品。如果我做

ProductGroups.Where(x => x.ParentId == null) 

這將返回根。我希望能夠以儘可能最小的方式返回完整的樹(不包括禁用的項目)(即在查詢集合後不使用for循環)。

ProductGroup1 (IsEnabled == true) 
    | 
    --------- ProductGroup2 (IsEnabled == true) 
    |    | 
    |    ----------- ProductGroup4 (IsEnabled == false) 
    | 
    --------- ProductGroup4 (IsEnabled == false) 

即返回ProductGroup1與1名兒童ProductGroup2

感謝

+0

LINQ總是會返回一個平坦的IEnumerable,所以你要查找的內容(真的)是樹的根?真的嗎?如果是這樣,爲什麼不向ProductGroup添加一個返回已啓用子項(僅)的函數並將該函數與您的根一起使用?或者你真的試圖讓IEnumerable包含所有已啓用的節點及其子節點到樹葉? – Kevek

回答

0

我不知道你與過濾收集的具體需求。我正在將它看作View-Model。和遞歸擴展方法爲您提供了一個巧妙的方法來實現這個過濾器:

public static class Helper 
{ 
    public static ICollection<ProductGroup> EnabledWithChildren(this ICollection<ProductGroup> source) 
    { 
     var result = new List<ProductGroup>(); 
     foreach (var ele in source) 
     { 
      if(ele.IsEnabled == true) 
      { 
       var productGroup = new ProductGroup{Id = ele.Id, IsEnabled = ele.IsEnabled, ParentId = ele.ParentId}; 
       if(ele.Children != null && ele.Children.Count() > 0) 
        productGroup.Children = ele.Children.EnabledWithChildren(); 
       result.Add(productGroup); 
      } 
     } 
     return result; 
    }  
} 

與用法:

public class ProductGroup 
{ 
    public int Id; 
    public int? ParentId; 
    public ICollection<ProductGroup> Children; 
    public bool IsEnabled; 

    static void Main() 
    { 
     var filteredProductGroups = ProductsGroups.EnabledWithChildren(); 
    } 
} 
+0

問題在於,所有產品組都將在過濾之前加載到內存中。如果可能的話,我想讓EF使用一些巧妙的LINQ來進行過濾,即對IQueryable進行過濾,以便只從數據庫返回所需的記錄。我的數據集可能有數百萬條記錄,所以重要的是我可以使用EF來正確地過濾記錄。 – SturmUndDrang