C# 为什么在这个linq查询中会出现编译时错误?
我在编译以下代码时遇到编译时错误,我看不出原因:C# 为什么在这个linq查询中会出现编译时错误?,c#,linq,entity-framework,C#,Linq,Entity Framework,我在编译以下代码时遇到编译时错误,我看不出原因: 关系是多对多的关系 var contacts = groups_to_querry .SelectMany(x => x.Contacts) .Where(x => x.ID == Guid.Empty) .SelectMany(p => p.ContactDetails) .Where(x =>
关系是多对多的关系
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
var contacts=组到查询
.SelectMany(x=>x.Contacts)
.Where(x=>x.ID==Guid.Empty)
.SelectMany(p=>p.ContactDetails)
.Where(x=>x.ID==Guid.Empty)
.选择多个(x=>x个联系人)//这一行给了我一个编译时错误
//错误:方法'System.Linq.Enumerable.SelectMany'的类型参数为
//(System.Collections.Generic.IEnumerable,System.Func)“”无法从使用中了解。
//尝试显式指定类型参数
当您第二次呼叫。选择many(x=>x.Contacts)
时,您当前使用的是一组联系人详细信息。您能否在其上使用SelectMany
是值得怀疑的。您需要使用选择
SelectMany
用于选择多个项目集合并将其放入一个IEnumerable
中<代码>选择
用于单个字段。由于您使用的对象类型为ContactDetail
(我假设只能有一个联系人),因此需要使用Select
编辑:简而言之,以下是您一步一步地做的事情:
groups\u to\u query.SelectMany(x=>x.Contacts)
:从我要查询的所有组中,选择他们的所有联系人。每个组都有许多联系人,因此将它们全部放入一个IEnumerable
类型Contact
。其中(x=>x.ID==Guid.Empty)
:…但仅限于ID为空的联系人
。选择多个(p=>p.ContactDetails)
:然后选择所有这些联系人的多个ContactDetails。每个联系人都有许多ContactDetails,因此将它们全部放入一个IEnumerable
类型的集合ContactDetail
.Where(x=>x.ID==Guid.Empty)
:…但仅限ID为空的ContactDetails
。选择多个(x=>x.Contacts)代码>:现在选择ContactDetails中的每个联系人。但是,由于编译器知道Contacts和ContactDetails之间存在一对多关系(而不是相反),因此该语句不可能执行,因此在您第二次调用时显示编译错误,您当前使用的是一组联系人详细信息
。您能否在其上使用SelectMany
是值得怀疑的。您需要使用选择
SelectMany
用于选择多个项目集合并将其放入一个IEnumerable
中<代码>选择
用于单个字段。由于您使用的对象类型为ContactDetail
(我假设只能有一个联系人),因此需要使用Select
编辑:简而言之,以下是您一步一步地做的事情:
groups\u to\u query.SelectMany(x=>x.Contacts)
:从我要查询的所有组中,选择他们的所有联系人。每个组都有许多联系人,因此将它们全部放入一个IEnumerable
类型Contact
。其中(x=>x.ID==Guid.Empty)
:…但仅限于ID为空的联系人
。选择多个(p=>p.ContactDetails)
:然后选择所有这些联系人的多个ContactDetails。每个联系人都有许多ContactDetails,因此将它们全部放入一个IEnumerable
类型的集合ContactDetail
.Where(x=>x.ID==Guid.Empty)
:…但仅限ID为空的ContactDetails
。选择多个(x=>x.Contacts)代码>:现在选择ContactDetails中的每个联系人。但是,由于编译器知道Contacts和ContactDetails之间存在一对多关系(而不是相反),因此该语句不可能出现,因此显示了一个编译错误,我将您的预期查询解释为“从多组联系人中,选择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()添加另一个筛选器,如果没有
编辑:因为您使用的是实体框架,所以上述操作可能不起作用。您可能需要在子查询中选择详细信息,然后在执行后在内存中进行筛选:
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);
我将您的预期查询解释为“从多组联系人中,选择ID=Guid.Empty的所有联系人以及ID=Guid.Empty的所有详细信息”
实际解释代码的方式是“从具有Guid.Empty的所有联系人中,选择具有Guid.Empty的所有详细信息,然后从这些详细信息中选择所有联系人”。第一个问题是,您最终会从详细信息中进行选择。这意味着最后的SelectMany
应该是Select