使用实体框架,但这可能无关紧要 如果我有一个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<SubItem> SubItems { get; set; }
}
答案 0 :(得分:3)
我解释您的问题,因为您想要返回所有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:在SubItem
上添加引用其父Item
的属性。然后返回SubItem
列表。这样,您就可以同时满足SubItems
和Items
条件。
...如果你正在使用IEnumerable
,你可以这样做:
IEnumerable items = items
.Select(item =>
{
item.SubItems.Where(sub => sub.ID = 1);
return item;
}
);
答案 1 :(得分: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
我假设每个子项目都有一个“指向”其父项的链接。
答案 2 :(得分:1)
items.Where(i => i.SubItems.Any(subItem => subItem.Id == 1));
答案 3 :(得分: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它非常简单快速。我用了几个生产项目,节省了很多次。