我有一个List集合,其中包含一个List子集合作为其中的属性,我想根据某些属性的值过滤掉该子集合中的项目。
为了简化,我将主要集合THING和子集合SUBTHING。它们是不同的类型。可以有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的所有过滤,它显示SUBTHINGS,其中PROP1 = 1,2,3,其中PROP2为NULL而不是NULL。
我想要的是一个列出所有THING ID的集合,然后列出所有SUBTHINGS的名称,有点像这样:
THING.ID
SUBTHING.Name
SUBTHING.Name
THING.ID
SUBTHING.Name
SUBTHING.Name
是否可以在使用LINQ过滤THINGS时过滤SUBTHINGS,因为THING和SUBTHING是两种不同的类型?
答案 0 :(得分: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
答案 1 :(得分: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);
}
答案 2 :(得分: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))
答案 3 :(得分:0)
我不确定这些答案中的任何一个确实能给你你想要的东西(尽管它们很接近)。根据我的理解,您需要一个THING
列表,其中至少有一个SUBTHING
包含您感兴趣的值(在这种情况下,Prop1 == 1
和Prop2 != null
) 。这里有几个选项,只取决于您是从THING
还是SUBTHING
工作。
选项1:THING
方法。
您正在查看任何THING
符合条件的SUBTHING
。所以:
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
方法。
您正在查看所有SUBTHING
并找到符合条件的地方,并按照此处的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
,然后才会提取与之关联的THING
(而不是首先必须找到SUBTHING
匹配的SUBTHING
标准,然后选择它。)
选项3:混合方式。
这两者都有点。我们将从THING
中选择任何一种方式,所以不妨只执行选择。然后,如果任何投影的子集合包含任何元素,那么我们会使用Names
返回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
我认为最干净的选择。如果集合中有任何项目,则不带任何参数的集合上的{{1}}扩展方法将返回true。适合我们的情况。
希望有所帮助,让我们知道你的想法。