如何通过子对象值属性过滤实体类型框架对象?

时间:2013-07-20 23:32:44

标签: c# linq entity-framework

我有一个名为batch的实体框架对象,这个对象与项目有1对多的关系。

所以1批次有很多项目。每个项目都有很多问题。

我想过滤具有特定问题代码的批处理项目(x.code == issueNo)。 我写了以下但我得到了这个错误:

        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' 

错误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   

5 个答案:

答案 0 :(得分:3)

Select扩展方法需要一个返回布尔值的lambda表达式,但内部o.Issues.Select会向外部Select(o => o返回一个IEnumerable boolean,这会导致您获得异常。

尝试使用Any来验证至少有一个元素验证条件:

    items = batch.Select(
               b => b.Items.Where(
                             i => i.ItemOrganisations.Any(
                                     o => o.Issues.Any(x => x.Code == issueNo)
                                  )
                    )
            ); 

答案 1 :(得分:2)

如果我理解正确,你试图通过多层枚举来选择。在这些情况下,您需要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);

如果您需要避免重复项目,可以随时将其包装在Distinct中:

var items = (from item in batch.Items
            from org in item.ItemOrganizations
            from issue in org.Issues
            where issue.Code == issueNo
            select item).Distinct();

答案 2 :(得分:0)

根据您的代码很难说出您要做的事情,但我认为您正在寻找类似的内容;

var issue = batch.Select(b => b.Items).Select(i => i.Issues).Where(x => x.Code == issueNo).Select(x => x).FirstOrDefault();

上述查询将返回第一个问题,其中“问题代码”属性等于issueNo。如果不存在此类问题,则返回null。

您的查询中的一个问题(第一个错误的原因)是您正在使用select,就像它是查询末尾的where子句一样。选择用于投射参数,当你执行Select(x => x.Code == issueNo)你正在做的是将x.Code投射到bool时,该选择返回的值是x.Code == issueNo的结果,看起来像你想要在where子句中使用该条件,然后你想返回满足它的问题,这就是我的查询正在做的事情。

答案 3 :(得分:0)

items =  from b in batch.Include("Items")
         where b.Items.Any(x=>x.Code==issueNo)
         select b;

答案 4 :(得分:0)

你迷失在lambdas中。你的LINQ链都是相互嵌入的,这使得它更难以推理。我在这里推荐一些辅助函数:

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信用),但我认为它更容易阅读。

相关问题