Linq "Impossible de traduire l'expression ... en SQL et ne pouvait pas la traiter comme une expression locale."
J'ai commencé avec cette questionj'ai répondu il yet maintenant, je te pose la question plus fondamentale ici. J'ai simplifié la requête:
var q = from ent in LinqUtils.GetTable<Entity>()
from tel in ent.Telephones.DefaultIfEmpty()
select new {
Name = ent.FormattedName,
Tel = tel != null ? tel.FormattedNumber : "" //this is what causes the error
};
tel.FormattedNumber
est une propriété qui combine la Number
et Extension
des champs dans un soigneusement chaîne formatée. Et voici l'erreur que les résultats:
System.InvalidOperationException: Could not translate expression 'Table(Entity).SelectMany(ent => ent.Telephones.DefaultIfEmpty(), (ent, tel) => new <>f__AnonymousType0`2(Name = ent.FormattedName, Tel = IIF((tel != null), tel.FormattedNumber, "")))' into SQL and could not treat it as a local expression.
Si je change la référence ci-dessus à partir de FormattedNumber
à tout simplement Number
tout fonctionne bien.
Mais je ne veux le nombre formaté pour afficher joliment dans ma liste. Que recommandez-vous comme la plus élégante, la plus propre façon de faire?
source d'informationauteur Shaul Behr | 2009-08-12
Vous devez vous connecter pour publier un commentaire.
Vous pouvez utiliser
AsEnumerable
sur l'entité, mais qui l'obligerait à ramener toutes les colonnes (même si pas utilisé); peut-être plutôt quelque chose comme:où
FormatNumber
est une méthode qui prend les deux et les fusionne, sans doute ré-utilisé à partir de votre autre (de la propriété) du code.Avec LINQ-to-SQL, une autre option est d'exposer un UDF sur les données de contexte qui fait la mise en forme à l'intérieur de la base de données; un exemple légèrement différent:
(qui va faire le travail à la base de données; si oui ou non c'est une bonne idée ;-p)
Le propre est d'indiquer les domaines que vous voulez vraiment dans l'expression, les mettre dans votre milieu des objets de la couche, puis utilisez toutes les fonctions auxiliaires pour modifier ce dernier.
Je ne sais pas si vous vous rendez compte qu'une classe représentant la table SQL pour LINQ est un DTO classe définit la grammaire utilisée par LINQ-SQL traducteur. L'injection d'une propriété dans un DTO qui n'est pas mappé à la table SQL n'est pas encore pris en charge ce qui signifie que le traducteur peut, feu à volonté. Les attributs définissent la grammaire et de ce qui n'est pas définie par eux n'existe pas d'expression traducteur.
Entités dont le nom figure dans la clause from ne sont pas des objets, ils sont juste des symboles utilisés pour aider à l'orthographe réel les champs de la table qui seront récupérées. Un terrain pas explicitement nommée dans select est un champ ne peut trouver - au moins c'est le but du traducteur, il peut avoir à laisser un peu de glisser à travers. Par exemple, si l'ent.FormattedName n'est pas déclaré, c'est un glissement et peut exploser dernier.
Donc, que FormattedNumber propriété injecté dans DTO classe n'existe même pas dans la grammaire. Ce n'est pas un "champ calculé" - ce terme est strictement pour SQL définitions de table et si vous en avait un, il serait dans la DTO de la grammaire. Notez que l'erreur a dit très justement, "l'expression locale" - portée très limitée.
Vous pourriez essayer de tricher par un imbriquée lambda expression de l'invocation d'une fonction statique dans l'ensemble, "tel", ce qui pourrait triger aller chercher de l'ensemble de l'enregistrement ou de lancer une autre exception.
Autres LINQ-s, qui ne sont pas des traducteurs, peut avoir des règles assouplies. LINQ-SQL doit être très stricte ou très lent, et il est déjà assez lent 🙂
@Marc Gravel me battre pour la réponse, le crédit pour les différentes answerers à cette question qui m'a mis sur la piste.
Je l'ai fait un peu comme Marc première suggestion, comme suit:
Et qui l'ont fait!
Merci à tous!