[英]Using Func<> in LINQ Query
我有一个Func<ProductItemVendor, bool>
存储在CompareProductItemVendorIds
。 我想在 LINQ 查询中使用该表达式。
看起来以下是合法的:
var results =
Repository.Query<ProductItemVendor>().Where(CompareProductItemVendorIds);
但是,以下情况是不合法的:
var results = from v in Repository.Query<ProductItemVendor>()
where CompareProductItemVendorIds(v)
select v;
此代码产生错误:
LINQ to Entities 不支持 LINQ 表达式节点类型“Invoke”。
问题:
为什么这些语句如此不同,以至于我的Func<>
在其中一个是合法的,而在另一个中不合法? 我认为他们基本上都做了同样的事情。
我怎样才能使这项工作? 我是否必须明确创建我的Func<>
作为Expression<Func<>>
代替?
Expression<Func<T,bool>>
和Func<T,bool>
之间有很大的区别。 第一个是表达式树。 您可以将其视为代码的描述。 Linq to Entities 需要表达式树。 因为它需要构建 SQL 查询。 所以它需要代码描述来将相同的操作转换为 SQL。
第二个, Func<T,bool>
是一个带有指定签名的简单方法。 这里没什么特别的。 为什么它在这里合法:
Repository.Query<ProductItemVendor>().Where(CompareProductItemVendorIds);
这很简单。 有两种Where
扩展方法。 一个前IQueryable<T>
,它期望表达式树(将被转换为 SQL 查询)。 另一个是IEnumerable<T>
扩展,它需要用于内存中集合过滤的序数方法(通常是 C# 代码)。 因此你没有表达式树,选择后一个。 这里没有生成 SQL。 这是你的情况。
现在第二个查询:
from v in Repository.Query<ProductItemVendor>()
where CompareProductItemVendorIds(v)
select v
实际上这不是相同的查询。 它相当于
Repository.Query<ProductItemVendor>().Where(v => CompareProductItemVendorIds(v));
在这里你有 lambda 表达式,它可以转换成表达式树。 另一个Where
扩展被使用 - 一个用于IQueryable<T>
。 因此,Linq to Entities 尝试将此表达式树转换为 SQL。 但它应该转换什么? 是的,调用一些内存中的方法。 当然,Linq to Entities 没有做到这一点。
为了使您的查询工作,您应该使用Expression<Func<T,bool>>
。 您可以手动构建它,也可以使用 lambda 表达式。
你的第一个版本有效的原因是 Linq 太聪明了,不利于它自己。 相当于你的第一个版本实际上是
IEnumerable<ProductItemVendor> temp = Repository.Query<ProductItemVendor>().AsEnumerable();
var results = temp.Where(CompareProductItemVendorIds);
所以,当你执行你查询你在你的数据库返回的每一行,然后执行Where
在本地计算机上的内存。
要在数据库上执行 Where 子句,您必须将CompareProductItemVendorIds
的类型更改为Expression<Func<ProductItemVendor, bool>>
。
无法从Func<TIn, TOut>
“转换”到Expression<Func<TIn. Tout>>
Expression<Func<TIn. Tout>>
,您必须将代码重写为最初是一个表达式,然后您可以通过调用CompareProductItemVendorIds.Compile()
转换为Func<TIn, TOut>
Expression<Func<ProductItemVendor, bool>> CompareProductItemVendorIds = //...
Func<ProductItemVendor, bool> CompareProductItemVendorIdsAsFunc = CompareProductItemVendorIds.Compile();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.