【问题标题】:How to filter entities based on 2nd degree relationship如何根据二级关系过滤实体
【发布时间】:2025-12-02 03:40:01
【问题描述】:

我使用 EntityFramework Core 的数据库架构简化了这一点:

public class Parent
{
    public int ID { get; set; }
}

public class Child
{
    public int ID { get; set; }
    public bool Include { get; set; }
}

public class Link
{
    public int FromID { get; set; }
    public int ToID { get; set; }
}

父项通过第三个表中的条目链接到子项。 父链接是一对多的 与孩子的链接是一对一的

作为这项工作的一部分,我无法更改数据库架构。

我正在尝试返回与至少一个孩子相关联且所有孩子都满足特定条件的 Parent 实例(在此示例中为 include == true

我尝试了很多不同的查询,包括下面的一个,它在这个测试场景中有效,但似乎不能很好地扩展。

var ParentList = new[]
{
    new Parent {ID = 1}, //3 children, 1 fails criteria
    new Parent {ID = 2}, //2 children, all pass criteria
    new Parent {ID = 3}  //no children
};
var ChildList = new[]
{
    new Child {ID = 11, Include = true},
    new Child {ID = 12, Include = true},
    new Child {ID = 13, Include = false},
    new Child {ID = 21, Include = true},
    new Child {ID = 22, Include = true},
};
var LinkList = new[]
{
    new Link {FromID = 1, ToID = 11},
    new Link {FromID = 1, ToID = 12},
    new Link {FromID = 1, ToID = 13},
    new Link {FromID = 2, ToID = 21},
    new Link {FromID = 2, ToID = 22},
};

var relevant = (from parent in ParentList
    join l in LinkList on parent.ID equals l.FromID into links
    from linkedChildren in (
        from link in links
        join child in ChildList on link.ToID equals child.ID into children
        from child in children
        group child by link.FromID into kids
        select kids.AsEnumerable())
    where linkedChildren.All(x => x.Include)
    select new { parent, linkedChildren }).ToList();

Assert.Single(relevant);
Assert.Equal(2, relevant.First().parent.ID);

【问题讨论】:

    标签: c# entity-framework linq entity-framework-core linq-to-entities


    【解决方案1】:

    其中任何一个都应该为您指明正确的方向

    ParentList.Where(s => s.LinkList .Any(e => e.ChildList.Include == true))
    
    from s in dc.ParentList
    from e in s.LinkList 
    where e.ChildList.Include == true
    select s;
    

    看看这是否更符合您的需要:

    var result = from l in LinkList
                 join p in ParentList on l.FromID equals p.ID
                 join c in ChildList on l.ToID equals c.ID and c.Include == true
                 select new { p.ID, c.ID, l.FromID, l.ToID};
    

    【讨论】:

    • 在我的例子中,ParentChild 中的 ID 字段不是 Link 中的外键(链接是一种链接到许多不同表的通用方式)。所以在我的模型中Parent 没有LinkList 属性,同样Link 没有ChildList 属性,这就是我手动加入集合的原因。
    • @Sbaldwin 我改变了我的答案。它现在应该符合您的要求。
    • 更新后的答案会为父级和“include==true”子级之间的每个链接返回一条记录。我需要的是任何父实体的结果集,其中所有子实体都是'include==true'。