10

J'ai le code LINQ suivant:Impossible de convertir IQueryable <> à l'erreur IOrderedQueryable

var posts = (from p in db.Posts 
     .Include("Site") 
     .Include("PostStatus") 
     where p.Public == false 
     orderby p.PublicationTime 
     select p); 

     if (!chkShowIgnored.Checked) { 
      posts = posts.Where(p => p.PostStatus.Id != 90); 
     } 

Cette dernière ligne (supplémentaire où) me donne l'erreur:

Impossible de convertir implicitement système de type ». Linq.IQueryable 'to' System.Linq.IOrderedQueryable '.

Je ne suis pas sûr de ce que cela signifie ...
Pourquoi ai-je cette erreur?
Il est apparu une fois que j'ai ajouté la clause "orderby" à la requête, avant qu'elle ne soit bien compilée, donc j'ai une sorte de pressentiment de ce qui se passe, mais je ne peux pas vraiment y mettre le doigt.

Répondre

19

Essayez déclarant posts spécifiquement comme IQueryable<Post> plutôt que var (qui décrochez le IOrderedQueryable<Post> (il sera toujours être commandé).

Vous pouvez également re- structurez-le donc nous commandons à la fin, ce qui nous permet de (éventuellement) introduire le where au milieu:

var posts = from p in db.Posts 
      .Include("Site") 
      .Include("PostStatus") 
      where p.Public == false 
      select p); 

if (!chkShowIgnored.Checked) { 
    posts = posts.Where(p => p.PostStatus.Id != 90); 
} 
var finalQuery = posts.OrderBy(p => p.PublicationTime); 

(évidemment, nous regardons finalQuery)

La raison pour laquelle il est erroring est que vous avez actuellement (essentiellement):

IOrderedQueryable<Post> posts = {snip}; 
... 
posts = {something (Where) that returns IQueryable<Post>} 
+0

Les deux ont fonctionné comme un charme, merci! Que voulez-vous dire que nous commandons à la fin plutôt que dans le milieu? Le SQL réel n'est-il pas généré et exécuté après tout ceci, une fois la requête énumérée? Je suppose que LINQ serait assez intelligent pour "combiner" les WHERE ... –

+5

C'est OrderBy qui change la signature ... en faisant le OrderBy la dernière chose que nous appliquons, nous avons 'IQueryable ' partout, ce qui est plus facile composer. Comme vous le dites, le fournisseur (EF, LINQ-to-SQL, etc) va tout fusionner avant de l'exécuter quand même. –

+0

Aaaaah, cette dernière explication est SUPER clair, gotcha. Je vous remercie!! –

-5

Le résultat de l'expression lambda de type IQueryable. Il ne permet pas la méthode d'extension Where, donc pour l'utiliser d'abord vous devez convertir cela en, par exemple, une liste.

Vous pouvez le faire en utilisant

posts = posts.ToList().Where(p => p.PostStatus.Id != 90); 
+4

Hmmmmm, mais ne serait pas la première exécution d'une requête qui va apporter tous les enregistrements de la base de données, puis les filtrer par statut dans ASP.Net? Je préfère avoir le processus DB tous les WHERE, ce qui est ce que je pensais arrivé si je venais d'ajouter la clause .Where, puisque le SQL serait généré et exécuté plus tard, lorsque les résultats sont énumérés. Dans votre cas, ToList() ne l'exécute-t-il pas aussi? –