Как фильтровать сущности на основе отношений 2-й степени - PullRequest
1 голос
/ 22 мая 2019

Я использую 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 голосов
/ 22 мая 2019

Любой из них должен направить вас в правильном направлении

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