0

我有一个 List 集合,其中包含一个 List 子集合作为其中的属性,并且我想根据某些属性的值过滤掉该子集合中的项目。

为简化起见,我将调用主集合 THING 和子集合 SUBTHING。它们是不同的类型。THINGS 可以有 1 到多个 SUBTHINGS。SUBTHING 有 2 个我想过滤的属性,PROP1 应该等于 1(它可以等于 1、2、3),PROP2 不应该是 NULL(它可以包含一个字符串)。

因此,当我使用像下面这样的查询时,它似乎给了我想要的东西(尽管我不确定 All() 是否符合我的预期):

search = from c in search
where c.SUBTHING.All(s=>s.PROP1==1)
select c;

然后当我添加其他属性时我会怀疑:

search = from c in search
where c.SUBTHING.All(s=>s.PROP1==1 && s.PROP2 != NULL)
select c;

我得到了 PROP2 为 Null 的东西。

当我切换到 Any() 时,我失去了对 SUBTHING 的所有过滤,它显示了 PROP1 = 1、2、3 以及 PROP2 为 NULL 而不是 NULL 的 SUBTHINGS。

我想要得到的是一个列出所有 THING ID 的集合,然后列出所有 SUBTHINGS 的名称,有点像这样:

THING.ID
     SUBTHING.Name
     SUBTHING.Name

THING.ID
     SUBTHING.Name
     SUBTHING.Name

由于 THING 和 SUBTHING 是两种不同的类型,这是否也可以在使用 LINQ 过滤 THINGS 时过滤 SUBTHINGS?

4

4 回答 4

1

尝试这样的事情:

search = 
    from c in search 
    where c.SUBTHING.All(s=>s.PROP1==1 && s.PROP2 != NULL) 
    select new {
         ThingId = c.ThingID,
         Something = c.SomeThing.Select(x=>x.Name)
     }; 

要对子项应用过滤器,请尝试:

from product in products
where product.productid == 1
from image in product.productimages
where image.ismainimage
select image.imagename

来自:101 个 linq 查询

于 2012-08-20T15:42:31.283 回答
0

一种方法是使用Enumerable.Where匿名类型:

var result = from thing in search
         from subthing in thing.subthings
         where subthing.prop1 == 1 && subthing.prop2 != null
         select new {ID = thing.ID, Name = subthing.Name};

foreach(var x in result)
{
    Console.WriteLine("ID={0} Name{1}", x.ID, x.Name);
}
于 2012-08-20T15:44:20.473 回答
0

您在查询父实体 ( THING) 时需要一个投影,但在结果集中您只想拥有它的一个子集SUBTHINGS

您可以通过以下方式进行操作:

class Thing
{
    Thing(Thing original, IEnumerable<Subthing> subthings)
    {
        // Initialize based on original and set the collection
        //
        ...
    }
}

然后像这样运行查询:

var filtered = from c in search
               select new Thing(c, c.Subthings.Where(x => x.PROP1 == 1 && x.PROP2 != null))
于 2012-08-20T15:45:32.063 回答
0

我不确定这些答案中的任何一个是否真的能满足您的需求(尽管它们很接近)。据我了解,您需要一个THINGs 列表,其中至少 1SUBTHING具有您感兴趣的值(在本例中为Prop1 == 1Prop2 != null)。这里有几个选项,只取决于你是从一个角度THING还是一个SUBTHING角度工作。

选项1:THING接近。

您正在查看任何THINGSUBTHING您的情况有关的内容。所以:

var result = from thing in search
             where thing.Subthings.Any(tr => tr.Prop1 == 1 && tr.Prop2 != null)
             select new { ID = thing.ID, Names = thing.Subthings.Where(tr => tr.Prop1 == 1 && tr.Prop2 != null) };

选项2:SUBTHING接近。

您正在查看 ALLSUBTHING并找到满足条件的那些,然后按 ID 分组。

var result = from thing in search
             from sub in thing.Subthings
             where sub.Prop1 == 1 && sub.Prop2 != null
             group sub by thing.id into sg
             select new { ID = sg.Key, Names = sg.Select(tr => tr.Name) };

我更喜欢这种方法,但仍有改进的余地。我喜欢这个的原因是因为你SUBTHING首先找到了 s,然后它才会拉出THING与之关联的那个(而不是首先必须查找是否有SUBTHING匹配条件,然后选择它)。

选项 3:混合方法。

这两者都有一点。无论哪种方式,我们都会从SUBTHINGs 中选择,所以还不如只执行选择。然后,如果任何投影的子集合有任何元素,那么我们返回我们THINGNames.

var result = from thing in search
             let names = thing.Subthings
                              .Where(sub => sub.Prop1 == 1 && sub.Prop2 != null)
                              .Select(sub => sub.Name)
             where names.Any()
             select new { ID = thing.ID, Names = names };

在我看来,最干净的选择。Any如果集合中有任何项目,则不带任何参数的集合上的扩展方法将返回 true。非常适合我们的情况。

希望对您有所帮助,让我们知道您的想法。

于 2012-08-20T17:39:39.770 回答