C# 如何按子对象值属性筛选实体类型框架对象?
我有一个名为batch的实体框架对象,该对象与项有1对多关系 所以一批有很多项目。每一项都有很多问题 我想过滤具有特定问题代码(x.code==issueNo)的批处理项目。 我写了以下内容,但我收到了这个错误:C# 如何按子对象值属性筛选实体类型框架对象?,c#,linq,entity-framework,C#,Linq,Entity Framework,我有一个名为batch的实体框架对象,该对象与项有1对多关系 所以一批有很多项目。每一项都有很多问题 我想过滤具有特定问题代码(x.code==issueNo)的批处理项目。 我写了以下内容,但我收到了这个错误: items = batch.Select(b => b.Items .Where(i => i.ItemOrganisations .Select(o => o
items = batch.Select(b => b.Items
.Where(i => i.ItemOrganisations
.Select(o => o
.Issues.Select(x => x.Code == issueNo))));
错误1:
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<bool>>' to 'bool'
无法将类型“System.Collections.Generic.IEnumerable”隐式转换为“bool”
错误2:
Cannot convert lambda expression to delegate type 'System.Func<Ebiquity.Reputation.Neptune.Model.Item,bool>' because some of the return types in the block are not implicitly convertible to the delegate return type
无法将lambda表达式转换为委托类型“System.Func”,因为块中的某些返回类型不能隐式转换为委托返回类型
Select
扩展方法需要一个返回布尔值的lambda表达式,但内部的o.Issues.Select
将布尔值的IEnumerable返回给外部的Select(o=>o
,这将导致您得到的异常
尝试使用Any
来验证是否至少有一个元素验证了条件:
items = batch.Select(
b => b.Items.Where(
i => i.ItemOrganisations.Any(
o => o.Issues.Any(x => x.Code == issueNo)
)
)
);
如果我理解正确,您正在尝试通过多层枚举进行选择。在这种情况下,您需要
SelectMany
,而不是select
。LINQ的语法糖专门用于使SelectMany
更易于推理:
var items = from item in batch.Items
from org in item.ItemOrganizations
from issue in org.Issues
where issue.Code == issueNo
select item;
编译器将其转换为如下内容:
var items = batch.Items
.SelectMany(item => item.ItemOrganizations, (item, org) => new {item, org})
.SelectMany(@t => @t.org.Issues, (@t, issue) => new {@t, issue})
.Where(@t => @t.issue.Code == issueNo)
.Select(@t => @t.@t.item);
如果需要避免重复项目,您可以始终将其包装在一个不同的中:
var items = (from item in batch.Items
from org in item.ItemOrganizations
from issue in org.Issues
where issue.Code == issueNo
select item).Distinct();
很难根据您的代码判断您正在尝试做什么,但我认为您正在寻找类似的东西
var issue = batch.Select(b => b.Items).Select(i => i.Issues).Where(x => x.Code == issueNo).Select(x => x).FirstOrDefault();
上述查询将返回Issues Code属性等于issueNo的第一个问题。如果不存在此类问题,则将返回null
查询中的一个问题(第一个错误的原因)是,您在查询末尾使用select,就像它是where子句一样。select用于在执行select(x=>x.code==issueNo)时投影参数
您所做的是将x.code投影到布尔,该选择返回的值是x.code==issueNo
的结果,似乎您希望在where子句中包含该条件,然后您希望返回满足该条件的问题,这就是我的查询所做的。您正在lambdas中迷失。您的LINQ链是all相互嵌入,更难推理。我推荐一些助手函数:
items = from b in batch.Include("Items")
where b.Items.Any(x=>x.Code==issueNo)
select b;
static bool HasIssueWithCode(this ItemOrganization org, int issueNo)
{
return org.Issues.Any(issue => issue.Code == issueNo);
}
static bool HasIssueWithCode(this Item items, int issueNo)
{
return items.ItemOrganizations.Any(org => org.HasIssueWithCode(issueNo));
}
那么你的答案简单明了
var items = batch.Items.Where(item => item.HasIssueWithCode(issueNo));
如果您内联这些函数,结果与manji的完全相同(因此请将正确答案归功于manji),但我认为这更容易阅读。我现在没有编译器,但类似的东西可能会工作:items=batch.items.Select(x=>x.Issues.Any(I=>I.Code==issueNo));您可能不想这样排列您的语句。这意味着您一直在处理批处理。manji的答案有更多惯用的间距,但如果您发现自己做得这么多,可能最好制作一些帮助函数,如我的第二个答案。@xer说manji的答案会快一点,因为他的Select
只返回一次项目。如果项目上存在多个问题,且相应的问题不存在,则我的项目将返回多次。因此,我的项目需要Distinct
,而manji的项目不应该需要它。