12
votes

Différence entre la distribution et l'intérieur d'une sélection de Linq

Ce code jette une exception: xxx pré>

l'exception: p> xxx pré>

Ce code fonctionne: p> xxx

pourquoi comme code> autorise la conversion et couler code> ne p>

Je comprends que code> sera code> Remettre NULL et CAST lancerait une exception si l'un ou l'autre appelle échoue. D'accord. Mais lorsque j'exécute ce code: P>

var query = services
             .SomeQuery(bar);
var result = query.ToList(); 


4 commentaires

Il retourne un résultat de requête plus grand car il n'y a pas de clause?


Qu'est-ce que foo ? Une structure?


Quel type somequery retourne-t-il? Comment est-il lié à foo ?


FOO hérités de bar et il renvoie iquéryable


3 Réponses :


1
votes

C'est une différence dans la manière dont la distribution directe fonctionne vs. Comment fonctionne l'opérateur comme fonctionne. La fonte directe n'est pas disponible car vous n'utilisez pas de type de valeur - cela ne fonctionne que pour les primitives.

MAINTENANT, votre Lambda tente à la fois de sélectionner et de projeter - vous pourriez casser cela en deux opérations, donc: xxx

sur le plus grand nombre de résultats: vous manquez un clause là-bas.


0 commentaires

7
votes

LINQ to Entities est pas le même que LINQ to Objects. Alors que LINQ aux fonctions Les objets peuvent prendre un délégué correspondant et invoquer aveuglément comme code normal C #, LINQ to Entities traite vos lambdas comme des arbres d'expression parce qu'il a besoin de comprendre la sémantique de ces lambdas (et pas seulement leur signature) et les transformer à une requête équivalente pour votre backend EF. Bien entendu, cela signifie que LINQ to Entities ne peut pas gérer toutes les opérations que LINQ to Objects peut.

Maintenant, comme vous l'avez dit, une différence entre la coulée et en utilisant comme est que la coulée lance une exception en cas d'échec et comme retourne null . Mais il y a une différence encore plus importante entre les deux: 0 commentaires


3
votes

Il y a une différence importante entre les deux déclarations qui montrent que plus que tout (comme des règles CLR), le cadre d'entité est profondément impliqué ici.

  1. x comme FOO est traduit en SQL. EF peut faire cela parce qu'il sait qu'il retournera toujours un résultat, soit un FOO ou null. Le SQL généré est monstrueux au fait, mais cela fait le travail.

  2. (foo) x est pas traduit en SQL. EF sait qu'il n'ya aucun moyen de créer des objets foo pour tous x 's, comme la demande de sémantique de Cast Sémantique, et elle jette une exception. < / p>

    Notez que EF acceptera foos.select (f => (bar) f) , car il est toujours possible de créer un type de base à partir d'un sous-type. La distribution réelle est effectuée après la réception du résultat SQL, cela n'affecte pas le SQL lui-même.

    Il acceptera également bar.oftype (). Sélectionnez (x => (foo) x) (allément c'est assez inutile).

    donc le message d'erreur ...

    linq aux entités ne prend en charge que les types primitifs ou énumérations d'EDM coulés.

    ... n'est pas entièrement vrai. EF accepte les moulages quand ils sont faisables. Donc, à l'intérieur du traducteur de requêtes de EF, il n'y a qu'un tas de logique pour décider s'il vaut ou non l'effort de générer une déclaration SQL.


1 commentaires

+1, agréable de savoir qu'il soutient la simplification simple. Je suppose que le message d'erreur est trompeur précisément parce que (comme Eric Lippert le place), l'opérateur de distribution tente de signifier deux choses essentiellement contradictoires. Il semble que l'auteur de ce message d'erreur n'ait eu qu'un seul des deux à l'esprit à ce moment-là.