3

使用实体框架,但这可能无关紧要

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

类 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; }
}
4

4 回答 4

3

我将您的问题解释为无论如何您都想返回所有Items内容,但您想过滤SubItems. 对于IQueryable. 如果需要,您必须使用 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引用它的 parent上添加一个属性Item。然后返回一个列表SubItem。这样,您将同时拥有满足您的条件的地方SubItemsItems

...如果您正在使用 anIEnumerable您可以执行以下操作:

IEnumerable items = items
    .Select(item =>
        {
            item.SubItems.Where(sub => sub.ID = 1);
            return item;
        }
    );
于 2013-05-31T21:05:32.523 回答
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

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

于 2013-05-31T21:06:30.347 回答
1
items.Where(i => i.SubItems.Any(subItem => subItem.Id == 1));
于 2013-05-31T21:07:05.850 回答
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,非常简单快捷。我在几个生产项目中使用了它,它为我节省了大量时间。

于 2013-06-01T13:21:46.357 回答