使用表达式<;Func<>>;在LINQ查询中
本文关键字:lt gt LINQ 查询 Func 表达式 | 更新日期: 2023-09-27 18:28:07
我想定义一个名为CompareProductItemVendorIds
的Func<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查询中使用它?
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
,实体已经加载。假设dbContext
或objectContext
延迟加载与显式加载的实现方式有点不同,我假设您使用的是显式加载。如果您将加载更改为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的调用被剥光了。