Why does LINQ-to-Entites recognize my custom method?

只谈情不闲聊 提交于 2019-12-18 04:44:19

问题


This works:

Entities.WorkOrderSet.Where(MyCustomMethod);

This does not:

Entities.WorkOrderSet.Where(o => MyCustomMethod(o));

([Edit] Even without new, it doesn't work)

I understand why the second doesn't work - but why in the world does the first work!? Shouldn't I get a "LINQ-to-Entities does not recognize the method..." at runtime, like with the second?

For reference, here is MyCustomMethod

public bool MyCustomMethod(WorkOrder workOrder)
{
    return !workOrder.WorkOrderNum.StartsWith("A", StringComparison.CurrentCultureIgnoreCase);
}

Using EF1, not EF4


回答1:


First works because it is an extension method and is is executing the query as a func, and then filtering your list see here. So in general it would automatically cast the where to

 Where(Func<WorkOrder, bool>

Second doesn't because it is pushing your where statement down to the db. When the lambda expression is evaluated it is expanded like this:

Where( Expresion<Func<WorkOrder, bool>>)

Here is a good article that explains Expressions vs Func

Here is another SO post that helps to explain the difference

[Edit (BlueRaja)]

This new edit appears to be correct. To clarify: it seems Func<WorkOrder, bool> is implicitly castable to Expression<Func<WorkOrder, bool>>, but not the other way around.

There are overloads of Where for both types. .Where(MyCustomMethod) is calling the Func<WorkOrder, bool> one, whereas .Where(o => MyCustomMethod(o)) is calling the Expression<Func<WorkOrder, bool>> one.




回答2:


Just forming this as an "answer" here, instead of a comment..

I think this is a new feature in .NET 4, where the framework realises that this function cannot be translated to SQL, but can be easily processed in memory. So it gets the whole dataset to the local machine and continues the query processing..

The thing is your first snippet, when translated to an expression tree, would directly say that it runs an external method, while your second snippet is not so "direct". I suppose this is why in the first case L2E can easily understand what's going on, and decide what to do, while in the second case it "thinks" it's better to send an exception and let the developers scratch their heads some more ^_^



来源:https://stackoverflow.com/questions/2675536/why-does-linq-to-entites-recognize-my-custom-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!