Linq 查询,该查询检索具有集合的子项的父项/子项

本文关键字:查询 子项 检索 Linq 集合 | 更新日期: 2023-09-27 18:33:51

我有一个自引用Category类,如果它至少有一个子类别并且在集合中至少有一个或多个活动(ICollection<Activity>(,我想从中检索父类别和所有相应的子类别。

这也适用于儿童的孩子,因为只有当存在至少具有 1 个或多个活动的儿童类别时,才应返回这些类别。

如果没有至少包含 1 个或多个活动的子类别,则不应返回父项或子项Category

查询应将父Category作为实际Category对象返回,而不仅仅是CategoryId。这可能吗?

public class Category
{
    public int CategoryId { get; set; }
    public string Name { get; set; }
    public int? ParentId { get; set; }
    public virtual Category Parent { get; set; }
    public virtual ICollection<Category> Children { get; set; }
    public virtual ICollection<Activity> Activities { get; set; }
}

更新 1

部分有效的查询:

 var categories = _db.Categories
        .Where(x => x.Parent != null &&  x.Activities.Count > 0)
        .GroupBy(x => x.ParentId)
        .Select(g => new { Parent = g.Key, Children = g.ToList() }).ToList();

Linq 查询,该查询检索具有集合的子项的父项/子项

让我们从小一点开始,因为您要创建的查询有些复杂。我们将自下而上创建您的查询。首先,您希望消除没有任何子类别的类别,这些子类别至少具有一个或多个活动。让我们做一个Predicate,在一个级别上为应该包含的内容返回true,为应该排除的内容返回false。我们将分两个阶段进行。首先,让我们创建一个谓词,为具有活动的类别返回true

Predicate<Category> hasActivities = cat => cat.Activities.Any();

其次,让我们创建一个Predicate,为那些具有具有活动的子类别的类别返回true

Predicate<Category> hasChildWithActivities = 
    parentCat => parentCat.Children.Any(hasActivities);


现在让我们创建一个过滤器查询,该查询将过滤给定Category的后代。为此,我们将创建一个Func,该采用父Category,执行逻辑并返回更新的Category

Func<Category, Category> getFilteredCategory =
    parentCat => 
    {
        parentCat.Children = parentCat.Children
            .Where(hasChildWithActivities)
            .Select(getFilteredCategory);
        return parentCat;
    });

请注意,这相当于:

Func<Category, Category> getFilteredCategory = delegate(Category parentCat)
{
    parentCat.Children = parentCat.Children
        .Where(hasChildWithActivities)
        .Select(getFilteredCategory);
    return parentCat;
};


在你的OP中,你提到你也想过滤父母。您可以通过遍历到顶级并运行此查询,或者通过使用"joins"或更复杂的"select"语句创建单独的查询,在父级上使用相同的逻辑。恕我直言,后者可能会很混乱,我建议不要这样做。如果你也需要将逻辑应用于父级,那么首先向上遍历树。无论哪种方式,这都应该给你一个好的开始。


如果您有任何问题,请告诉我。祝你好运,编码愉快!:)