Dans certaines situations, la requête LINQ to Entities doit renvoyer une sous-chaîne en fonction de la longueur de la chaîne. Voici la requête:
var query = ( from f in Context.Files orderby f.DateAdded descending select new { Concerns = f.Concerns.Name, Sender = f.Sender.Name, CategoryCount = f.Categories.Count(), DateAdded = f.DateAdded, Comment = (f.Comment == null || f.Comment.Length < 5) ? f.Comment : f.Comment }).Take(10);
Je cherche donc à obtenir les 10 dernières entités de type Fichiers ajoutées, puis à sélectionner un ensemble de propriétés à afficher dans une liste. Certains sont des chaînes simples (Concerns, Sender). CategoryCount renvoie le nombre de catégories associées à l’object File.
Cependant, je souhaite que le commentaire soit tronqué s’il est plus long qu’une longueur donnée. Dans le code ci-dessus, tout fonctionne correctement. Maintenant, quand je remplace cette ligne:
Comment = (f.Comment == null || f.Comment.Length < 5) ? f.Comment : f.Comment
Avec cette ligne:
Comment = (f.Comment == null || f.Comment.Length < 5) ? f.Comment : f.Comment.SubString(0,5)
l’application lève une XamlParseException (???)
L’appel du constructeur sur le type ‘DocumentManager.Views.ListEnsortingesView’ qui correspond aux contraintes de liaison spécifiées a généré une exception.
Je ne sais vraiment pas pourquoi il ferait cela. La méthode SubSsortingng n’est-elle pas prise en charge dans LINQ?
J’espère que quelqu’un pourra m’aider ici. Jusque-là, je vais le laisser tel quel.
EDIT 2 (En quelque sorte, ma première édition s’est perdue. Je la refais donc): Sur la base des commentaires que j’ai reçus, j’ai changé mon code pour ceci et cela fonctionne maintenant:
var query = App.Context.Files.OrderByDescending(File => File.DateAdded).Take(10).AsEnumerable() .Select(File => new { Concerns = File.Concerns.Name, Sender = File.Sender.Name, CategoryCount = File.Categories.Count(), DateAdded = File.DateAdded, Comment = (File.Comment == null || File.Comment.Length < 100) ? File.Comment : File.Comment.Substring(0, 100) + "..." });
J’ai oublié de mentionner que j’utilise SQLite. Alors peut-être que Subssortingng n’est pas implémenté dans le fournisseur SQLite EF.
Je ne sais pas avec certitude, mais je soupçonne que la sous-chaîne n’est pas prise en charge par Linq-to-Entities. Je déplacerais votre Take (10) avant votre instruction select, puis après Take (10), appelez AsEnumerable (), puis votre instruction select après cela. Cela vous obligera à récupérer une collection de fichiers de la firebase database, puis la projection se fera en mémoire.
Ce n’est pas la faute de LINQ en fait. Votre modèle est lié à IQueryable, c’est-à-dire aux routines directement sockets en charge par votre firebase database (tout le rest jette des exceptions). Vous devez utiliser la méthode AsEnumerable à un moment donné pour faire tout le rest.
Lisez-en plus ici sur Bill Wagner pour expliquer la différence entre IQueryable et IEnumerable:
Cela semble être un bogue dans l’parsingur SQLite car
La sous-chaîne fonctionne correctement pour interroger une firebase database SQL Server avec LINQ to Entities
Si vous consultez le journal SQL généré, il le génère sous la forme d’une fonction SQL de sous-chaîne.
Dans SQLite, la fonction correcte est substr et non une chaîne
Ainsi, il existe un bogue dans la façon dont il génère la requête.
Voici un moyen de corriger ce bug.
Dans votre modèle de firebase database, ajoutez ce code juste avant EntityContainer
Dans votre classe de contexte (créez une classe partielle à côté), ajoutez ce code
[DbFunction("MyModel.Store", "substr")] public ssortingng SubStr(ssortingng text, int startPos) { return text.Subssortingng(startPos); }
Dans votre code, appelez Subssortingng de cette façon
context.SubStr(text, startpos)
Il va maintenant mapper correctement à la fonction SUBSTR au lieu de SUBSTRING! C’est comme mapper une fonction définie par l’utilisateur, sauf que nous mappons à une fonction standard existante.
J’espère que cela t’aides!
Correct – LINQ ne prend pas en charge la sous-chaîne, mais l’exception n’est pas toujours très claire lorsque vous essayez des choses comme celle-là, malheureusement.