2013-05-31 58 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它非常简单和快速。我用它生产项目,它节省了我的吨。