我正在尝试从对象列表中选择一个对象列表,该对象列表本身具有基于该对象列表中的属性的另一种类型的对象列表。
例如
class TypeA{
string Name {get; set;}
List<TypeB> ListOfTypeB {get; set;}
}
class TypeB{
int Age {get; set;}
bool Active {get; set;}
}
我有一个由数据库填充的 A 类型列表,我想查询 TypeA 列表并根据 TypeB 中的 Active 属性返回一个 TypeA 列表,它是 TypeA 对象中的一个列表。
任何帮助都会很棒。
谢谢
你写道:
我想查询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
的真实值。
可查询
如果您的数据库设置正确,您将有两个表。一张桌子放
TypeA
物品,一张桌子放TypeB
物品。
TypeA
与 TypeB
是一对多的关系。每个 TypeA
都有零个或多个 TypeB
并且每个 TypeB
恰好属于一个 TypeA
.
在您的数据库中,
TypeA
和 TypeB
都有一个主键。每个TypeB
都会有一个外键指向它所属的TypeA
。
这是相当标准的数据库。它可以帮助您进行查询。使用这些定义,您的查询将被翻译成:
我想要所有 TypeA 对象,其中至少有一个 TypeB 对象具有此 TypeA 对象的外键和 Activity 的真值
查询将是:
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 对象
这实际上取决于您如何实现过滤器逻辑。如果你想找到类型 A 的列表,其中类型 B 包含至少一个活动标志,那么你可以像下面那样做。
listOfTypeA.Where(a => a.ListOfTypeB.Any(b => b.Active)).ToList();