简体   繁体   English

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

[英]Using Expression<Func<>> in a LINQ Query

I want to define a Func<ProductItemVendor, bool> filter expression named CompareProductItemVendorIds , which can be used throughout my application, mostly within Entity Framework/LINQ queries. 我想定义一个名为CompareProductItemVendorIdsFunc<ProductItemVendor, bool>过滤器表达式,它可以在我的应用程序中使用,主要是在Entity Framework / LINQ查询中。

I've learned that in order to be able to use this filter in a LINQ query, I must declare it as Expression<Func<>> instead of just Func<> . 我已经了解到,为了能够在LINQ查询中使用此过滤器,我必须将其声明为Expression<Func<>>而不仅仅是Func<> I understand the reason for this, and it's easy for me to do this. 我理解这个的原因,这对我来说很容易。

But I'm having the following problems using that expression in my queries. 但是我在查询中使用该表达式时遇到以下问题。

First, code such as: 首先,代码如:

ProductItem.ProductItemVendors.FirstOrDefault(CompareProductItemVendorIds)

Note: ProductItem is a database entity, and its ProductItemVendors property is a navigation collection. 注意: ProductItem是一个数据库实体,其ProductItemVendors属性是导航集合。

Produces the error: 产生错误:

`Instance argument: cannot convert from 'System.Collections.Generic.ICollection' to 'System.Linq.IQueryable' `Instance参数:无法从'System.Collections.Generic.ICollection'转换为'System.Linq.IQueryable'

And second, code such as: 第二,代码如:

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

Produces the error: 产生错误:

'CompareProductItemVendorIds' is a 'variable' but is used like a 'method' 'CompareProductItemVendorIds'是'变量',但用作'方法'

So I have my nice shiny new Expression<Func<>> . 所以我有一个很好的闪亮的新Expression<Func<>> How can I use it in my LINQ queries? 如何在LINQ查询中使用它?

ProductItem is already an Entity , so you can't use your Expression, you need to use Compile () to get the Func<> from your Expression<Func<>> since ProductItemVendors is no longer an IQueryable ProductItem已经是一个Entity ,所以你不能使用你的Expression,你需要使用Compile ()从你的Expression<Func<>>获取Func<> ,因为ProductItemVendors不再是一个IQueryable

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

You would have to use your Expression on the ProductItemVendorsContext like this: 您必须在ProductItemVendorsContext上使用Expression,如下所示:

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

You cant use an Expression inside query syntax, you need to use method sytanx 您无法在查询语法中使用Expression,您需要使用方法sytanx

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

The first case; 第一个案例;

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

Produces the error: 产生错误:

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

Happens because it is an ICollection , the entity has already been loaded. 发生因为它是ICollection ,实体已经被加载。 Given dbContext or objectContext lazy loading vs explicit loading is implemented a bit differently, I assume you are using explicit loading though. 鉴于dbContextobjectContext延迟加载与显式加载的实现略有不同,我假设您使用的是显式加载。 If you change the loading to lazy the type of ProductItemVendors will be IQueryable and what you are trying will succeed. 如果将加载更改为延迟,则ProductItemVendors的类型将为IQueryable并且您尝试的内容将成功。

Given the second case, the expression must be compilable to SQL , else you get a lot of weird errors, probably it's possible that that is the case here. 鉴于第二种情况,表达式必须可编译为SQL ,否则会出现许多奇怪的错误,可能在这种情况下就是这种情况。

It's hard to give you more explicit help given the information in the question, I cannot recreate it easily. 鉴于问题中的信息,很难给你更明确的帮助,我无法轻易地重新创建它。 If you can create a MWE-solution and upload it somewhere I can have a look, but I'm afraid I can't help more here. 如果你可以创建一个MWE解决方案并将其上传到某个地方我可以看看,但我担心我在这里无法提供更多帮助。

I don't think composing expressions like that is supported by default. 我不认为默认情况下支持组合这样的表达式。
You could try LINQKit 你可以尝试LINQKit

Here's an example from the LINQKit page; 这是LINQKit页面的一个例子; one Expression<Func<>> inside another: 另一个Expression<Func<>>

Call Invoke to call the inner expression Call Expand on the final result. 调用Invoke以调用最终结果的内部表达式Call Expand。 For example: 例如:

 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 and Expand are extension methods in LINQKit.) Here's the output: (Invoke和Expand是LINQKit中的扩展方法。)这是输出:

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

Notice that we have a nice clean expression: the call to Invoke has been stripped away. 请注意,我们有一个很好的干净表达式:对Invoke的调用已被删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM