在LINQ查询中使用Func <>

Jon*_*ood 4 c# linq func

我有一个Func<ProductItemVendor, bool>存储CompareProductItemVendorIds.我想在LINQ查询中使用该表达式.

看来以下是合法的:

var results =
    Repository.Query<ProductItemVendor>().Where(CompareProductItemVendorIds);
Run Code Online (Sandbox Code Playgroud)

但是,以下内容不合法:

var results = from v in Repository.Query<ProductItemVendor>()
              where CompareProductItemVendorIds(v)
              select v;
Run Code Online (Sandbox Code Playgroud)

此代码产生错误:

LINQ to Entities不支持LINQ表达式节点类型"Invoke".

问题:

  1. 为什么这些陈述如此不同以至于我Func<>的合法而不是另一个?我认为他们基本上都做了同样的事情.

  2. 我怎样才能做到这一点?我是否必须明确地创建我的Func<>作为Expression<Func<>>代替?

在LINQ查询中的Using Expression <Func <>>中查看我的相关问题.

Ser*_*kiy 11

Expression<Func<T,bool>>和之间有很大的不同Func<T,bool>.第一个是表达式树.您可以将其视为代码描述.Linq to Entities需要表达式树.因为它需要构建SQL查询.因此需要将代码描述为将相同的操作转换为SQL.

第二个,Func<T,bool>是一个带有指定签名的简单方法.这里没什么特别的.为什么它在这里合法:

Repository.Query<ProductItemVendor>().Where(CompareProductItemVendorIds);
Run Code Online (Sandbox Code Playgroud)

这很简单.有两种Where扩展方法.首先IQueryable<T>,它需要表达式树(将被翻译成SQL查询).另一个是扩展IEnumerable<T>,期望内存收集过滤的顺序方法(通常的C#代码).因此,您没有表达式树,选择后者.这里没有生成SQL.这是你的情况.

现在第二个查询:

from v in Repository.Query<ProductItemVendor>()
where CompareProductItemVendorIds(v)
select v
Run Code Online (Sandbox Code Playgroud)

实际上它不是同一个查询.它相当于

Repository.Query<ProductItemVendor>().Where(v => CompareProductItemVendorIds(v));
Run Code Online (Sandbox Code Playgroud)

在这里你有lambda表达式,可以转换为表达式树.并使用另一个Where扩展 - 一个用于IQueryable<T>.因此,Linq to Entities尝试将此表达式树转换为SQL.但它应该转换成什么?是的,调用一些内存中的方法.当然,Linq to Entities没有这样做.

为了使您的查询有效,您应该使用Expression<Func<T,bool>>.您可以手动构建它,也可以使用lambda表达式.


Sco*_*ain 5

你的第一个版本工作的原因是Linq太聪明了,因为它本身就是好事.实际上相当于你的第一个版本

IEnumerable<ProductItemVendor> temp = Repository.Query<ProductItemVendor>().AsEnumerable();
var results = temp.Where(CompareProductItemVendorIds);
Run Code Online (Sandbox Code Playgroud)

因此,当您执行查询时,您将返回数据库中的每一行,然后Where在本地计算机上执行内存.

为了让Where子句要在数据库上执行,你必须改变的类型CompareProductItemVendorIdsExpression<Func<ProductItemVendor, bool>>.

没有办法"转换" Func<TIn, TOut>Expression<Func<TIn. Tout>>,你必须重写你的代码最初是一个表达式,然后你可以Func<TIn, TOut>通过调用转换为CompareProductItemVendorIds.Compile()

Expression<Func<ProductItemVendor, bool>> CompareProductItemVendorIds = //...
Func<ProductItemVendor, bool> CompareProductItemVendorIdsAsFunc = CompareProductItemVendorIds.Compile();
Run Code Online (Sandbox Code Playgroud)