2010-04-20 3 views
9

Cela fonctionne:Pourquoi LINQ-to-Entites reconnaît-il ma méthode personnalisée?

Entities.WorkOrderSet.Where(MyCustomMethod); 

Cela ne signifie pas:

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

([Modifier] Même sans new, il ne fonctionne pas)

Je comprends pourquoi la deuxième ne fonctionne pas - mais pourquoi dans le monde fait le premier travail !? Devrais-je obtenir un "LINQ-to-Entities ne reconnaît pas la méthode ..." à l'exécution, comme avec la seconde?

Pour référence, voici myCustomMethod

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

En utilisant EF1, pas EF4

+0

Quelle exception obtenez-vous lorsque vous essayez d'exécuter le second? –

+0

Etes-vous sûr que EF n'obtient pas seulement la totalité de la table et exécute la fonction localement lorsque vous exécutez votre premier shippet? Exécutez le profileur SQL et vérifiez quelle requête est envoyée au serveur? –

+0

Je reçois "LINQ-To-Entities ne peut pas reconnaître la méthode ..." - c'est le comportement attendu, car les méthodes personnalisées ne peuvent pas être traduites en SQL. La solution habituelle est d'appeler .ToList() d'abord ... mais pour une raison quelconque, il semble fonctionner sans cela! –

Répondre

6

D'abord fonctionne parce qu'il est une méthode d'extension et exécute la requête en tant que Func, puis Filtrer votre liste see here. Donc, en général, il jetterait automatiquement où

Where(Func<WorkOrder, bool> 

deuxième ne pas parce qu'il pousse votre déclaration où jusqu'à la db. Lorsque l'expression lambda est évaluée, il est étendu comme celui-ci:

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

Voici une bonne article qui explique Expressions vs Func

Here is another SO post that helps to explain the difference

[Modifier (BlueRaja)]

Cette nouvelle modification semble être correcte. Pour clarifier: il semble Func<WorkOrder, bool> est implicitement castable à Expression<Func<WorkOrder, bool>>, mais pas l'inverse.

Il existe des surcharges de Where pour les deux types. .Where(MyCustomMethod) appelle le Func<WorkOrder, bool> un, tandis que .Where(o => MyCustomMethod(o)) appelle le Expression<Func<WorkOrder, bool>>.

+1

Veuillez vérifier à nouveau .. Il peut utiliser une classe anonyme, mais sa méthode personnalisée recevra toujours un objet WorkOrder en tant que paramètre, tandis que votre code ne sera même pas compiler :) –

+0

Peut-être que j'aurais dû élaborer (voir modifier ci-dessus): le code compile, mais il échoue à l'exécution en raison de * "LINQ to Entities ne reconnaît pas la méthode ..." * Exemple: http://blog.dreamlabsolutions.com/post/2008/11/17/LINQ-Method- ne peut pas-être-traduit-dans-une-expression-de-magasin.aspx Ceci est attendu, mais le fait que le premier fonctionne est inattendu! –

+0

@Nouveau look: P new {WorkOrder = o} est en effet une classe anonyme ... Inside. Où (o => ...) o est la classe anonyme .. Alors que o.WorkOrder est de type WorkOrder .. dans ce cas, le paramètre qui est passé dans sa fonction est du type correct! –

1

formant juste cela comme une « réponse » ici, au lieu d'un commentaire ..

Je pense que c'est une nouvelle fonctionnalité dans .NET 4, où le cadre se rend compte que cette fonction ne peut pas être traduit en SQL, mais peut être facilement traité en mémoire. Donc, il récupère tout le jeu de données sur la machine locale et continue le traitement de la requête.

La chose est votre premier extrait, lorsqu'il est traduit dans un arbre d'expression, dirait directement qu'il exécute une méthode externe, alors que votre second extrait est pas si "direct". Je suppose que c'est pourquoi dans le premier cas L2E peut facilement comprendre ce qui se passe, et décider quoi faire, alors que dans le second cas il "pense" qu'il vaut mieux envoyer une exception et laisser les développeurs gratter la tête un peu plus^_^

+0

En utilisant EF1, qui est .Net 3.5 –

+0

peut-être c'est une chose EF1 vs L2S 1 alors? Ou peut-être que c'est une fonctionnalité qui existe depuis quelque temps maintenant? Quoi qu'il en soit - la meilleure explication que je puisse donner est que le framework essaie d'être intelligent, basé sur l'arbre d'expression dans lequel votre requête est compilée :) –

Questions connexes