“LINQ to Entities 不支持 LINQ 表达式节点类型 'Invoke'” - 难倒!
Posted
技术标签:
【中文标题】“LINQ to Entities 不支持 LINQ 表达式节点类型 \'Invoke\'” - 难倒!【英文标题】:"The LINQ expression node type 'Invoke' is not supported in LINQ to Entities" - stumped!“LINQ to Entities 不支持 LINQ 表达式节点类型 'Invoke'” - 难倒! 【发布时间】:2011-07-14 04:24:19 【问题描述】:稍后在我的 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();
但是,我收到上述错误。通过从函数构建谓词,我似乎一切都正确。有任何想法吗?谢谢。
【问题讨论】:
【参考方案1】:我遇到了这个错误,我正在使用由 Joe Albahari 编写的带有 PredicateBuilder 的实体框架来构建动态的 where
子句。如果你恰好处于同样的情况,你应该调用AsExpandable
方法:
如果使用 Entity Framework 进行查询,请将最后一行更改为:
return objectContext.Products.AsExpandable().Where(predicate);
此方法是 LINQKIT DLL 的一部分,您可以获取 here 或通过 NuGet 包 here。
现在一切正常。 :)
【讨论】:
您知道AsExpandable()
是否会对性能造成影响吗?我正在使用通用存储库并且仅偶尔使用谓词构建器,是否值得为谓词构建创建单独的存储库方法?
@Cody...我不知道。你最好直接问乔·阿尔巴哈里。 :) 这是他的推特:twitter.com/linqpad
@DoctorOreo 你知道性能影响了吗?我和你的情况一样
@Marc 你知道吗,自从我猜想 2014 年 4 月以来我一直在使用它,我还没有发现任何问题。现在在生产应用程序中进行了一年半,没有人抱怨。 (这是一个拥有约 50 个用户的系统,处理 10,000 到 5,000,000 条记录)
看起来在最新版本中您不需要使用AsExpandable()
将谓词传递给Where()
。可能是因为新的PredicateBuilder.New<T>()
起点?【参考方案2】:
您正在尝试将任意 .NET 函数传递给...实体框架如何希望将其转换为 SQL?您可以将其更改为采用Expression<Func<int, bool>>
,并从中构建Where
子句,尽管这并不容易特别,因为您需要用不同的表达式重写参数表达式(即用调用u.RelationTypeId
的表达式替换原始表达式树中的任何参数表达式)。
老实说,为了在 lambda 表达式中指定 u.RelationTypeId
,用于创建传递给方法的表达式树,最好只使用:
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 SO 上的某处是我写的一个示例,它将发生在Expression.Invoke
的扁平化,以允许 EF 使用子表达式(L2S 支持开箱即用的东西) .当然,它仍然无法与代表一起工作 - 只是说重写器在某个地方......
@Ryan here,其实就是启用“内联”
@Ryan @Marc 还有LinqKit,它包含了操作表达式所需的许多功能。
我赞同 Chris 对 LinqKit 的建议 => 它使得将 Expression您可以在Where
请求之前在predicate
上调用Expand()
方法。
【讨论】:
这也有效!而且我不知道 AsExpandable 做什么,所以我更喜欢在我真的想过滤查询时调用 Expand。【参考方案4】:我知道这个答案真的很晚了,但我遇到了同样的问题,它把我带到了这里,所以我想我会分享我的解决方案。
我阅读了 Leniel 的回答,它给了我一个想法。默认类型具有行为相同的方法“AsEnumerable()”,从而缓解了问题。
【讨论】:
AsEnumerable()
将导致 Linq to Objects 而不是 Linq to Entities 调用 Where()
函数。以上是关于“LINQ to Entities 不支持 LINQ 表达式节点类型 'Invoke'” - 难倒!的主要内容,如果未能解决你的问题,请参考以下文章