编译下面的代码时出现编译时错误,我看不出原因:
关系是多对多的关系
var contacts = groups_to_querry
.SelectMany(x => x.Contacts)
.Where(x => x.ID == Guid.Empty)
.SelectMany(p => p.ContactDetails)
.Where(x => x.ID == Guid.Empty)
.SelectMany(x => x.Contacts); //This line gives me a compile time error
//Error : The Type argumetns for method 'System.Linq.Enumerable.SelectMany<TSource,Tresult>
//(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,
//System.Collections.Generic.IEnumerable<TResult>>)' cannot be infrred from the usage.
//Try specifying the type arguments explicitly
答案 0 :(得分:4)
第二次致电.SelectMany(x => x.Contacts)
时,您目前正在使用ContactDetails
的集合。您可以在其上使用SelectMany
是值得怀疑的。您需要使用Select
代替。
SelectMany
时,会使用 IEnumerable
。 Select
用于各个字段。由于您正在使用ContactDetail
类型的对象(我假设只能有一个联系人),您需要使用Select
groups_to_querry.SelectMany(x => x.Contacts)
:从我要查询的所有群组中选择所有联系人。每个群组都有很多联系人,因此请将它们全部放入IEnumerable
Contact
个集合中
.Where(x => x.ID == Guid.Empty)
:...但仅限具有空ID的联系人
.SelectMany(p => p.ContactDetails)
:然后选择所有这些联系人的许多ContactDetails。每个联系人都有许多ContactDetails,因此将它们全部放入IEnumerable
类型的ContactDetail
个集合中
.Where(x => x.ID == Guid.Empty)
:...但只有那些ID为空的ContactDetails
.SelectMany(x => x.Contacts);
:现在选择每个ContactDetails的多个联系人。但是,由于编译器知道Contacts和ContactDetails之间存在一对多的关系(而不是相反),该语句是不可能的,因此显示编译错误
答案 1 :(得分:1)
我将您的预期查询解释为“来自多个联系人群组,选择ID = Guid.Empty的所有联系人,并且还包含所有ID = Guid.Empty的详细信息”。
您的代码实际解释的方式是“来自所有拥有Guid.Empty的联系人,选择所有具有Guid.Empty的详细信息,并从这些详细信息中选择所有联系人”。第一个问题是你最终会从细节中选择。这意味着最终的SelectMany
应该是Select
,因为x.Contacts
在这里指的是从详细信息到联系人的多对一关系。
第二个问题是结果将包含重复的联系人,因为每个细节都包含相同的联系人。您应该做的是直接根据其详细信息集过滤联系人,如下所示:
groups_to_query
.SelectMany(g => g.Contacts)
.Where(c => c.ID == Guid.Empty)
.Where(c => c.ContactDetails.All(d => d.ID == Guid.Empty))
请注意,这也会选择零详细信息的联系人,这与查询的行为不同,因此我不确定这是否是您想要的。如果没有,您可以为ContactDetails.Any()
添加另一个过滤器。
编辑:由于您使用的是Entity Framework,因此上述内容可能无效。您可能需要在子查询中选择详细信息,然后在执行后在内存中进行过滤:
var queryResult =
groups_to_query
.SelectMany(g => g.Contacts)
.Where(c => c.ID == Guid.Empty)
.Select(c => new {
contact = c,
detailIDs = c.ContactDetails.Select(d => d.ID)
}).ToList();
var contacts =
queryResult
.Where(r => r.detailIDs.All(id => id == Guid.Empty))
.Select(r => r.contact);