流畅的LINQ - 选择包含子项列表的父项列表,其中包含子项的子集

时间:2014-09-15 21:37:48

标签: c# sql linq fluent

那个头衔是最糟糕的......

无论如何,我要做的是选择一个包含n个子对象的父对象。我将传递子对象必须匹配的标准列表(1..n)。为了简洁起见,这里是我正在使用的课程:

public class Parent {

     public int Id { get; set; }

     public List<Child> Children { get; set; }

}

public class Child { 

    public int Id { get; set; }

    public int ParentId { get; set; }

    public int SomeValue { get; set; }

}

我正在寻找的是一份父母的名单,其中包含与我传入的所有SomeValues相匹配的孩子

所以,如果我有:

Parent 1
    Child 1, SomeValue 10
    Child 2, SomeValue 20
    Child 3, SomeValue 40
Parent 2
    Child 4, SomeValue 10
    Child 5, SomeValue 20
    Child 5, SomeValue 50

和myList是[10,50],它只需要返回Parent 2。如果myList是[10,20],则应返回父母双方。最后,如果myList是[10,20,60],则不应该返回任何内容。

我认为以下内容无效,因为孩子们在列表中没有的值会将其从结果中删除(对吗?)

parents.where(p => p.children.all(c => myList.contains(c.SomeValue)));

并且任何一个人都不会工作,因为只要其中一个孩子匹配,它就会返回任何东西。我需要确保父项具有匹配myList中每个项目的子项。我还想过添加一个计数以确保匹配的项目至少与myList.length一样大,但是这可能不起作用,因为SomeValue在子集合中不一定是不同的(我想我可以在孩子们的SomeValues上运行一个独特的子选择?)

2 个答案:

答案 0 :(得分:8)

您可以翻转条件,并检查以确保所有列表值都包含在Children集合中:

var matches = parents.Where(p => myList.All(v => p.Children.Select(c => c.SomeValue).Contains(v)));

答案 1 :(得分:0)

这里有一些粗略的代码输出:

10,20
1
2
10,50
2

var parents = new List<Parent>
            {
                new Parent
                {
                    Id = 1,
                    Children =
                        new List<Child>
                        {
                            new Child {SomeValue = 10},
                            new Child {SomeValue = 20},
                            new Child {SomeValue = 40}
                        }
                },
                new Parent
                {
                    Id = 2,
                    Children =
                        new List<Child>
                        {
                            new Child {SomeValue = 10},
                            new Child {SomeValue = 20},
                            new Child {SomeValue = 50}
                        }
                }
            };

            var val1 = 10;
            var val2 = 20;
            var query = from a in parents
                from b in a.Children
                where b.SomeValue == val1
                select a;

            var query2 = from a in parents
                        from b in a.Children
                        where b.SomeValue == val2
                        select a;

            Console.WriteLine("10,20");
            foreach(var parent in query.ToList().Intersect(query2.ToList()))
                Console.WriteLine(parent.Id);

            val1 = 10;
            val2 = 50;

            Console.WriteLine("10,50");
            foreach (var parent in query.ToList().Intersect(query2.ToList()))
                Console.WriteLine(parent.Id);