如何基于二阶关系过滤实体

时间:2019-05-22 15:16:19

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

我将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);

1 个答案:

答案 0 :(得分:0)

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

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