使用表达式<;Func<>>;在LINQ查询中

本文关键字:lt gt LINQ 查询 Func 表达式 | 更新日期: 2023-09-27 18:28:07

我想定义一个名为CompareProductItemVendorIdsFunc<ProductItemVendor, bool>过滤器表达式,它可以在我的整个应用程序中使用,主要在实体框架/LINQ查询中使用。

我了解到,为了能够在LINQ查询中使用此筛选器,我必须将其声明为Expression<Func<>>,而不仅仅是Func<>。我理解这其中的原因,而且我很容易做到这一点。

但是,在查询中使用该表达式会遇到以下问题。

首先,代码如:

ProductItem.ProductItemVendors.FirstOrDefault(CompareProductItemVendorIds)

注意:ProductItem是一个数据库实体,其ProductItemVendors属性是一个导航集合

产生错误:

`实例参数:无法从"System.Collections.Generic.ICollection"转换为"System.Linq.Iquery"

第二,代码如:

var results = from v in Repository.Query<ProductItemVendor>()
              where CompareProductItemVendorIds(v)
              select v;

产生错误:

"CompareProductItemVendorIds"是一个"变量",但与"方法"类似

所以我有了我漂亮闪亮的新Expression<Func<>>。如何在LINQ查询中使用它?

使用表达式<;Func<>>;在LINQ查询中

ProductItem已经是Entity,因此您不能使用Expression,您需要使用Compiler()从Expression<Func<>>获取Func<>,因为ProductItemVendor不再是IQueryable

ProductItem.ProductItemVendors.FirstOrDefault(CompareProductItemVendorIds.Compile())

您必须在ProductItemVendorsContext上使用表达式,如下所示:

var item = Context.ProductItemVendors.FirstOrDefault(CompareProductItemVendorIds);

您不能在查询语法中使用表达式,您需要使用方法sytanx

var results = from v in Repository.Query<ProductItemVendor>()
                                  .Where(CompareProductItemVendorIds)
              select v;

第一种情况;

ProductItemVendor productItemVendor = ProductItem.ProductItemVendors.FirstOrDefault(CompareProductItemVendorIds);

产生错误:

`Instance argument: cannot convert from 'System.Collections.Generic.ICollection' to 'System.Linq.IQueryable'

发生这种情况是因为它是ICollection,实体已经加载。假设dbContextobjectContext延迟加载与显式加载的实现方式有点不同,我假设您使用的是显式加载。如果您将加载更改为lazy,则ProductItemVendors的类型将为IQueryable,并且您正在尝试的操作将成功。

在第二种情况下,表达式必须可编译为SQL,否则会出现很多奇怪的错误,这里可能就是这种情况。

考虑到问题中的信息,很难给你更明确的帮助,我无法轻易地重现。如果你能创建一个MWE解决方案并将其上传到某个地方,我可以看看,但恐怕我在这里帮不了更多的忙。

我认为默认情况下不支持编写这样的表达式
你可以试试LINQKit

以下是LINQKit页面中的一个示例;一个Expression<Func<>>在另一个内:

调用Invoke以调用内部表达式对final调用Expand后果例如:

Expression<Func<Purchase,bool>> criteria1 = p => p.Price > 1000;
Expression<Func<Purchase,bool>> criteria2 = p => criteria1.Invoke (p)
                                                 || p.Description.Contains ("a");
Console.WriteLine (criteria2.Expand().ToString()); 

(Invoke和Expand是LINQKit中的扩展方法。)以下是输出:

p => ((p.Price > 1000) || p.Description.Contains("a"))

请注意,我们有一个很好的干净表达式:对Invoke的调用被剥光了。