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

时间:2013-03-26 20:02:16

标签: c# .net linq wcf-data-services odata

我正在尝试进行模块化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.ConstantExpression”类型的对象强制转换为“System.Linq.Expressions.LambdaExpression”。

我知道这是我的任何条款,因为如果我在声明中嵌入该条款,一切正常。

为什么我收到此错误?我怎样才能打破这个陈述而不是出错呢?


更新:使用表达式

我尝试使用这样的表达式:

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>'

2 个答案:

答案 0 :(得分:5)

您可以尝试定义orderAnyClause,如下所示:

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

我没有测试它,但是查询理解的工作方式(并且基于错误),除非将其作为表达式获取,否则它将无法对其进行任何操作。

答案 1 :(得分:0)

您的IQueryable需要使用expression trees才能转换查询 - 换句话说,它需要将代码视图作为数据,而不仅仅是可执行代码。

现在我并非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) - 但是值得先尝试一下这个简单的方法。