2013-05-31 59 views
2

使用實體框架,但這可能不相關 如果我有一個Iqueryable,如何過​​濾子列表並保持它IQueryable,所以它還沒有打到數據庫?過濾IQueryable子列表

如果我有10個項目,並且每個項目都有3個子項目,那麼如何過濾所有10個項目並將它們的子項目過濾到id = 1的位置?

類項目上有大約20屬性,所以我不希望用他們每個人的投影,因爲維護問題..

items = items.select(??);//how to do this so items are returned, and their children are filtered? 

class SubItem 
{ private int ID { get; set; } 
} 
class Item 
{ 
private List<SubItem> SubItems { get; set; } 
} 
+1

爲什麼不在發出查詢時只包含where子句? –

+0

好問題。原因是我正在尋找使用假數據對我的過濾器進行單元測試,而不是依賴於隨時間改變狀態的數據庫 –

回答

2

我理解你的問題,你想返回所有Items無論如何,但你想過濾SubItems。對於IQueryable,沒有好方法說「我想要返回此對象,但我想要修改版本的X屬性」。如果你想這樣,你將不得不使用select語句來選擇一個新對象。

選項1:返回單獨的數據

var itemsAndSubItems = items 
    .Select(item => new 
     { 
      Item = item, 
      SubItems = item.SubItems.Where(sub => sub.ID = 1) 
     } 
    ); 

,或者如果你不介意的熱切加載項到內存:

IEnumerable<Item> = items 
    .Select(item => new 
     { 
      Item = item, 
      SubItems = item.SubItems.Where(sub => sub.ID = 1) 
     } 
    ) 
    .ToList() 
    .Select(row => 
     { 
      var item = row.Item; 
      item.SubItems = row.SubItems; 
      return item; 
     } 
    ); 

選項2:返回類的一個新實例(這看起來你不想做)

IQueryable<Item> items = items 
    .Select(item => new Item 
     { 
      SubItems = item.SubItems.Where(sub => sub.ID == 1), 
      OtherProp = item.OtherProp 
      /*etc for the other properties on Item*/ 
     } 
    ); 

選項3:添加另一個屬性到你的班級。我至少推薦這個。請注意,您的查詢仍然會返回所有子項在這裏,當你訪問SubItemsWithIdOne

class Item 
{ 
    private List<SubItem> SubItems { get; set; } 
    private List<SubItem> SubItemsWithIdOne 
    { 
     get 
     { 
      return this.SubItems.Where(sub => sub.ID == 1); 
     } 
    } 
} 

方案4:添加引用它的父ItemSubItem的屬性。然後返回一個列表SubItem。通過這種方式,您可以在SubItemsItems之間符合條件。

...如果你有IEnumerable工作,你可以這樣做:

IEnumerable items = items 
    .Select(item => 
     { 
      item.SubItems.Where(sub => sub.ID = 1); 
      return item; 
     } 
    ); 
2

如果你想過濾的孩子到那裏的每個父母只有一個孩子,你需要從娃娃抓起,選擇他們的父母,不要碰父母的子項:

IQueryable<SubItem> childItems = context 
    .SubItems.Include("Item") 
    .Where(si => si.Id == 1 && si.Item.SomeAttr == someValue); 
//    ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
//     |       | 
//     |   Set a condition on the parent 
// Set a condition on the child 

我認爲各個子項有一個鏈接‘指點’回到它的父。

1
items.Where(i => i.SubItems.Any(subItem => subItem.Id == 1)); 
0

我想你在找什麼是SelectMany。作爲你的情況的例子是這樣的:

positiveItems = items.SelectMany(x => x.SubItem).Where(x=> x.ID == 1).Select(x=>x.Item); 
    //items still IQueryable , so we can concat it with another IQueryable 

    negativeItems = items.SelectMany(x=>x.SubItem).Where(x=>x.ID != 1).Select(x=>x.Item); 


    //just an using option 
    allItems = positiveItems.Concat(negativeItems); 

而只是一個建議。對於大量的參考對象集,您可以使用ValueInjecter它非常簡單和快速。我用它生產項目,它節省了我的噸。