2010-04-20 7 views
9

Esto funciona:¿Por qué LINQ-to-Entites reconoce mi método personalizado?

Entities.WorkOrderSet.Where(MyCustomMethod); 

Esto no es así:

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

([Editar] Incluso sin new, no funciona)

entiendo por qué la segunda no funciona - , pero ¿por qué en el mundo hace el primer trabajo? ¿No debería obtener un "LINQ-to-Entities no reconoce el método ..." en tiempo de ejecución, como con el segundo?

Para referencia, aquí es MyCustomMethod

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

El uso de EF1, no EF4

+0

¿Qué excepción obtienes cuando intentas ejecutar la segunda? –

+0

Además ... ¿está seguro de que EF no solo obtiene toda la tabla y ejecuta la función localmente cuando ejecuta su primer barco? Ejecute el generador de perfiles SQL y verifique qué consulta se envía al servidor. –

+0

obtengo "LINQ-To-Entities no puede reconocer el método ...": este es el comportamiento esperado, ya que los métodos personalizados no se pueden traducir a SQL. La solución habitual es llamar a .ToList() primero ... ¡pero por alguna razón parece que funciona sin eso! –

Respuesta

6

Primera funciona porque es un método de extensión y es está ejecutando la consulta como una func, y luego filtrando su lista see here. Así que, en general, se habría echado automáticamente el dónde

Where(Func<WorkOrder, bool> 

En segundo lugar, no hace porque está empujando su estado de cuenta donde hasta el db. Cuando se evalúa la expresión lambda se amplía de esta manera:

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

Aquí es un buen article que explica Expressions vs Func

Here is another SO post that helps to explain the difference

[Editar (BlueRaja)]

Esta nueva edición parece ser correcta. Para aclarar: parece que Func<WorkOrder, bool> es implícitamente convertible a Expression<Func<WorkOrder, bool>>, pero no al revés.

Hay sobrecargas de Where para ambos tipos. .Where(MyCustomMethod) está llamando al Func<WorkOrder, bool>, mientras que .Where(o => MyCustomMethod(o)) está llamando al Expression<Func<WorkOrder, bool>>.

+1

Por favor, compruebe de nuevo ... Puede estar utilizando una clase anónima, pero su método personalizado seguirá recibiendo un objeto WorkOrder como parámetro, mientras que su código ni siquiera compilará :) –

+0

Quizás debería haber elaborado (ver edición arriba): el código se compila, pero falla en tiempo de ejecución debido a * "LINQ to Entities no reconoce el método ..." * Ejemplo: http://blog.dreamlabsolutions.com/post/2008/11/17/LINQ-Method- can-be-translated-into-a-store-expression.aspx Esto es esperado, ¡pero el hecho de que el primero SÍ funcione es inesperado! –

+0

@Nix mira de nuevo: P new {WorkOrder = o} es de hecho una clase anónima ... Dentro. Donde (o => ...) o es la clase anónima ... Mientras que o.WorkOrder es del tipo WorkOrder ... en cuyo caso, el parámetro que se pasa a su función es del tipo correcto. –

1

Sólo formando esto como una "respuesta" aquí, en lugar de un comentario ..

Creo que esta es una nueva característica de .NET 4, donde el marco se da cuenta de que esta función no se puede traducir a SQL, pero se puede procesar fácilmente en la memoria. Por lo tanto, obtiene todo el conjunto de datos en la máquina local y continúa el procesamiento de la consulta.

La cosa es su primer fragmento, cuando se traduce a un árbol de expresiones, diría directamente que ejecuta un método externo, mientras que su segundo fragmento es no tan "directo". Supongo que es por eso que en el primer caso L2E puede entender fácilmente lo que está sucediendo y decidir qué hacer, mientras que en el segundo caso "piensa" que es mejor enviar una excepción y dejar que los desarrolladores se rasquen la cabeza un poco más^_^

+0

Usando EF1, que es .Net 3.5 –

+0

¿quizás es una cosa EF1 vs L2S 1 entonces? ¿O tal vez es una característica que ha estado allí desde hace algún tiempo? Sea lo que sea, la mejor explicación que se me ocurre es que el framework trata de ser inteligente, basándose en el árbol de expresiones en el que se compila tu consulta :) –

Cuestiones relacionadas