我试图从一个对象列表中选择一个对象列表,这些对象列表中的另一个类型的对象基于该对象列表中的属性。
例如
class TypeA{
string Name {get; set;}
List<TypeB> ListOfTypeB {get; set;}
}
class TypeB{
int Age {get; set;}
bool Active {get; set;}
}
我有一个由数据库填充的Type A列表,我想查询TypeA列表并根据TypeB对象中的TypeB中的Active属性返回TypeA列表。
任何帮助都会很棒。
由于
答案 0 :(得分:1)
具体取决于您实现过滤器逻辑的方式。如果你想找到类型B的列表,其类型B包含至少一个活动标志,那么你可以这样做。
listOfTypeA.Where(a => a.ListOfTypeB.Any(b => b.Active)).ToList();
答案 1 :(得分:1)
您写道:
我想查询TypeA列表并返回TypeA列表 TypeB中的Active属性。
这个规范有点不清楚。我假设您的意思是您希望所有TypeA
个对象至少有一个TypeB
个对象具有真值TypeB.Activity
(或那些具有假值的对象)。
答案取决于您是要将查询作为Enumerable
还是Queryable
来执行。用语言:您首先要将对象放入本地内存然后执行查询(AsEnumerable
)还是要让数据库执行查询(Asqueryable
)然后只返回有效值结果是本地记忆。
<强> AsEnumerable 强>
此方法效率不高,因为这意味着您在处理之前将完整的TypeA和TypeB表获取到本地内存。
但是你的查询很简单:
var AwithActivity = allTypeA
.Where(a => a.ListOfTypeB.Any(b => b.Activity));
用语言说:
从typeA
元素的完整序列中,仅采用那些至少有一个typeA
元素的ListOfTypeB
元素,其属性为Activity
的真值。
<强> AsQueryable已强>
如果您的数据库设置正确,您将有两个表。一个包含TypeA
个项目的表和一个包含TypeB
个项目的表。
TypeA
与TypeB
具有一对多的关系。每个TypeA
都有零个或多个TypeB
,而每个TypeB
只属于一个TypeA
。
在您的数据库中,TypeA
和TypeB
都有一个主键。每个TypeB
都会有TypeA
所有的外键。
这是相当标准的数据库。它可以帮助您查询。使用这些定义,您的查询将被翻译为:
我想要所有TypeA对象,其中至少有一个TypeB对象具有此TypeA对象的外键,并且是活动的真值
查询将是:
var results = TypeATable // groupjoin table TypeA with table TypeB
.GroupJoin(TypeBTable,
typeA => typeA.PrimaryKey, // from every typeA use the primary key
typeB => typeB.ForeignKey, // from every typeB use the foreign key to the TypeA
(a, allB) => new // for every A with all matching typeB:
{ // create a new anonymous type
A = a, // with the found A
HasActivity = allB // and a boolean that says if there was
.Any(b => b.Activity), // at least one B with a true Activity
});
要让所有TypeA至少有一项活动:
var AWithActivity = results.Where(result => result.HasActivity)
.Select(result => result.A);
要获得完全没有任何活动的所有TypeA:
var AwithoutActivity = result.Where(result => !result.HasActivity)
.Select(result => result.A);
<强>加成强> 如果可能是typeA和typeB之间的关系不是一对多,而是多对多。在这种情况下,您将获取所有活动的typeB对象并查找具有此活动typeB对象的外键的所有typeA对象