过滤IQueryable子列表

使用entity framework,但这可能无关紧要如果我有一个Iqueryable,我如何过滤子列表并保持IQueryable,以便它还没有达到数据库?

如果我有10个项目并且每个项目有3个子项目,我该如何过滤它以便返回所有10个项目并且它们的子项目被过滤到id = 1的位置?

class Item上有大约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 SubItems { get; set; } } 

我解释你的问题,因为你想要返回所有Items无论如何,但你想过滤SubItems 。 对于IQueryable没有好的方法可以说“我想要返回此对象,除了我想要修改版本的X属性”。 如果要这样,您将必须使用select语句来选择新对象。

选项1:单独返回数据

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

或者如果你不介意急切地将这些项目加载到内存中:

 IEnumerable = 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:返回class级的新实例(您似乎不想这样做)

 IQueryable 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:向您的class级添加另一个属性。 我推荐这个。 请注意,当您访问SubItemsWithIdOne时,您的查询仍将返回此处的所有子项

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

选项4:在SubItem上添加一个引用它的父Item 。 然后返回SubItem列表。 这样,您将拥有符合条件的SubItemsItems

…如果你正在使用IEnumerable你可以这样做:

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

如果您想将孩子过滤到每个父母只有一个孩子的地方,您需要从孩子开始,选择他们的父母,而不要触摸父母的子项:

 IQueryable 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 

我假设每个子项目都有一个“指向”其父项的链接。

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

我想你正在寻找的是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它非常简单快速。 我用了几个生产项目,节省了很多次。