如何在Any子句中分解Linq表达式

本文关键字:分解 Linq 表达式 子句 Any | 更新日期: 2023-09-27 18:06:12

我正试图使一个模块化的Linq查询(到OData来源)。

这是我的查询的简化版本:

// Any clause that I want to be modular
Func<Encounter, bool> orderAnyClause = x => x.OrderName.StartsWith("Order 00");
// Query using the any clause
var result = entities.Customers.Where(cust=> cust.Orders.Any(orderAnyClause));
// A method to do the selection.  It works just fine.
IQueryable<SearchSelectionResult> selectedResults = SelectResults(result); 
// This throws the exception shown below
var list = selectedResults.ToList();  

这些都编译得很好,但是当我运行它时,我的any子句导致了这个异常:

无法强制转换'System.Linq.Expressions '类型的对象。

我知道这是我的any子句,因为如果我在语句中嵌入了the子句,它就会正常工作。

为什么我得到这个错误?我怎样才能跳出这个语句而不出现错误呢?


更新:使用表达式

我试着用这样的表达:

Expression<Func<Encounter, bool>> orderAnyClause = 
                                      x => x.OrderName.StartsWith("Order 00");

我得到以下编译时错误消息:

Instance argument: cannot convert from System.Data.Services.Client.DataServiceCollection<ODataComponetizedQueriesTest.MyEntities.Order>' to 'System.Linq.IQueryable<ODataComponetizedQueriesTest.MyEntities.Order>'

如何在Any子句中分解Linq表达式

您可以尝试这样定义orderAnyClause:

Expression<Func<Encounter, bool>> orderAnyClause = 
                                        x => x.OrderName.StartsWith("Order 00");

我没有测试它,但是查询理解工作的方式(基于错误),它将无法对它做任何事情,除非它得到它作为一个表达式。

您的IQueryable需要使用表达式树来转换查询-换句话说,它需要将代码视为数据,而不仅仅是可执行代码。

现在我不能100%确定这将工作,但我希望你可以使用:

Expression<Func<Encounter, bool>> orderAnyClause =
    x => x.OrderName.StartsWith("Order 00");

…然后保持相同的代码。这样,您的orderByClause变量将引用表达式树,而不是委托。现在有可能无法工作-因为您在这里的另一个lambda表达式中使用了它:

cust => cust.Orders.Any(orderAnyClause)

…该lambda表达式也将转换为表达式树。这取决于OData提供程序用它做什么。您可能需要编写一个方法来做一些古怪的事情来构建cust.Orders.Any(orderAnyClause) -但值得先尝试简单的方法。