Linq lève une exception sur .Subssortingng ()

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:

http://msdn.microsoft.com/en-us/vcsharp/ff963710

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.