“ LINQ to Entities不支持LINQ表达式节点类型'Invoke'”-烦死了!


67

稍后在我的EF中,我试图传递一个匿名函数以用作Linq查询的一部分。该函数将传入INT并返回BOOL(u.RelationTypeId为INT)。以下是我的函数的简化版本:

public IEnumerable<UserBandRelation> GetBandRelationsByUser(Func<int, bool> relation)
{
    using (var ctx = new OpenGroovesEntities())
    {
        Expression<Func<UsersBand, bool>> predicate = (u) => relation(u.RelationTypeId);

        var relations = ctx.UsersBands.Where(predicate);

        // mapping, other stuff, back to business layer
        return relations.ToList();
    }
}

但是,我得到上述错误。似乎我通过从函数构建谓词来使所有事情都正确。有任何想法吗?谢谢。

Answers:


49

您正在尝试在...中传递任意.NET函数。实体框架如何希望将其转换为SQL?您可以将其改为取一个Expression<Func<int, bool>>,然后Where从中构建子句,尽管这并不是特别容易,因为您需要使用其他参数表达式重写表达式(即替换原始表达式中的任何参数表达式)表示的树u.RelationTypeId)。

坦白地说,为了只u.RelationTypeId在用于创建表达式树的lambda表达式中指定要传递到方法中,最好还是使用:

public IEnumerable<UserBandRelation> GetBandRelationsByUser(
    Expression<Func<UsersBand, bool>> predicate)
{
    using (var ctx = new OpenGroovesEntities())
    {
        var relations = ctx.UsersBands.Where(predicate);

        // mapping, other stuff, back to business layer
        return relations.ToList();
    }
}

谢谢。那是我的想法,但是我的问题是UserBandRelation是一个模型,而UsersBand是我的实体模型。我使用自动映射器来映射这些。如果我尝试一些疯狂的事情,例如映射表达式,Automapper就会出现问题。有什么办法可以使我的实体分开?谢谢。
Ryan Peters

1
我在SO上某处的@Ryan是我写的一个示例,它将平整化Expression.Invoke以允许EF与子表达式一起使用(L2S支持开箱即用)。当然,它仍然不能与代表一起工作-只是说重写者在这里……
Marc Gravell

1
实际上,@ Ryan在这里–仅启用“内联”
Marc Gravell

2
@Ryan @Marc还有LinqKit,其中包含操纵表达式所需的许多功能。
克里斯·皮特曼

2
克里斯的第二个建议是LinqKit =>,它使将Expression <Func <YourType,bool >>谓词链接在一起非常容易。
2013年

122

我遇到了这个错误,并且正在使用由Joe Albahari设计的带有PredicateBuilder的实体框架来构建动态where子句。如果碰巧处于相同状况,则应调用以下AsExpandable方法:

如果使用Entity Framework查询,则将最后一行更改为:

return objectContext.Products.AsExpandable().Where(predicate);

这种方法是LINQKIT DLL,你可以抓住的一部分,在这里或通过NuGet包在这里

现在一切正常。:)


2
您知道是否AsExpandable()会对性能产生影响吗?我使用的是通用存储库,偶尔仅使用谓词生成器,是否值得为谓词构建创建单独的存储库方法?
科迪2014年

1
@Cody ...我不知道。您最好直接向Joe Albahary询问。:)这是他的推特:twitter.com/linqpad
Leniel Maccaferri 2014年

1
@DoctorOreo您知道性能影响了吗?我和你的处境相同
Marc

@Marc,您知道吗,自从我猜是2014年4月以来,我一直在使用它,但是我没有发现任何问题。现在,在生产应用程序中运行了一年半,没有人抱怨。(这是一个拥有约50个用户的系统,处理10,000至5,000,000条记录)
Cody 2015年

2
看起来您不需要使用AsExpandable()谓词将最新版本传递给Where()。可能是因为新的PredicateBuilder.New<T>()起点?
Gup3rSuR4c


-7

我知道这个答案真的来晚了,但是我遇到了同样的问题,并把我引到了这里,所以我想我会分享我的解决方案。

我读了Leniel的答案,它给了我一个主意。默认类型具有方法“ AsEnumerable()”,该方法的行为相同,从而减轻了该问题。


11
AsEnumerable()将导致该Where()函数由Linq to Objects而不是Linq to Entities调用。
haim770
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.