2017-09-08 1 views
0

Ich habe die folgende Funktion:Linq Abfrage-Ergebnisse in Vergleichsoperatoren nicht für Typ unterstützt ‚System.Linq.IQueryable`1 [System.Int32]

public List<DTO.ArticleDTO> GetRecentArticles(int portalID, int moduleID, int domainID, int rootKnowledgeTypeID, int count) 
{ 
    var articles = 
     (from 
      article in _Context.Articles.LatestArticles(_Context.ArticleVersions, portalID, moduleID) 
      where _GetRootDomainsForArticle(article.ArticleID, article.Version, rootKnowledgeTypeID).Contains(domainID) 
     orderby article.UpdatedOn descending 
      select new ArticleDTO 
      { 
       ArticleID = article.ArticleID, 
       Title = article.Title, 
       Summary = article.Introduction, 
       Content = article.Content, 
       UpdatedOn = article.UpdatedOn, 
       Version = article.Version, 
       KnowledgeTypeText = (from 
             category in _Context.Categories 
            join 
             categoryVersion in _Context.ArticleCategoryVersions 
            on 
             category.CategoryID equals categoryVersion.CategoryID 
            where 
             categoryVersion.Version == article.Version && 
             categoryVersion.ArticleID == article.ArticleID && 
             category.ParentID == rootKnowledgeTypeID 
            select 
             category.Name 
           ).First() 
      }); 

    return articles.Take(count).ToList(); 
} 

Was ich versuche zu tun ist, bekommen alle Artikel, die zu einer Stammkategorie (Domänen-ID) gehören. Kategorien werden als Domänen/Subdomänen angesehen und jeder Artikel kann zu einer oder mehreren Domänen und Unterdomänen gehören. Deshalb habe ich die folgende Methode in der where-Klausel der obigen linq-Abfrage verwendet.

private IQueryable<int> _GetRootDomainsForArticle(int articleID, int version, int rootKnowledgeTypeID) 
{ 
    return from c in _Context.Categories 
        join cv in _Context.ArticleCategoryVersions on c.CategoryID equals cv.CategoryID 
        where cv.ArticleID == articleID 
        where cv.Version == version 
        where c.ParentID == null 
        where c.CategoryID != rootKnowledgeTypeID 
        select c.CategoryID; 
} 

Der Fehler, den ich bekommen ist: "Vergleichsoperator nicht für Typen unterstützt 'System.Linq.IQueryable`1 [System.Int32]'."

Ich denke, ist wegen der verzögerten Ausführung, aber ich verstehe nicht ganz den richtigen Weg, es zu tun.

Edit:

Basierend auf @SivaGopal Kommentar ich die Abfrage aus dem _GetRootDomainsForArticle bewegte Teil der Hauptabfrage zu werden, und es hat funktioniert:

public List<DTO.ArticleDTO> GetRecentArticles(int portalID, int moduleID, int domainID, int rootKnowledgeTypeID, int count) 
{ 
    var articles = 
     (from 
      article in _Context.Articles.LatestArticles(_Context.ArticleVersions, portalID, moduleID) 
      where (from c in _Context.Categories 
       join cv in _Context.ArticleCategoryVersions on c.CategoryID equals cv.CategoryID 
       where cv.ArticleID == article.ArticleID 
       where cv.Version == article.Version 
       where c.ParentID == null 
       where c.CategoryID != rootKnowledgeTypeID 
       select c.CategoryID).Contains(domainID) 
      orderby article.UpdatedOn descending 
      select new ArticleDTO 
      { 
       ArticleID = article.ArticleID, 
       Title = article.Title, 
       Summary = article.Introduction, 
       Content = article.Content, 
       UpdatedOn = article.UpdatedOn, 
       Version = article.Version, 
       KnowledgeTypeText = (from 
           category in _Context.Categories 
            join 
           categoryVersion in _Context.ArticleCategoryVersions 
          on 
           category.CategoryID equals categoryVersion.CategoryID 
            where 
           categoryVersion.Version == article.Version && 
           categoryVersion.ArticleID == article.ArticleID && 
           category.ParentID == rootKnowledgeTypeID 
            select 
           category.Name 
         ).First() 
      }); 

    return articles.Take(count).ToList(); 
} 

Mein begrenztes Verständnis von Linq mir führen zu Ich glaube, man könnte diese Anfrage auf eine Methode als Form der Abfragezusammensetzung aufteilen und sie dadurch wiederverwendbar machen. Scheint nicht der Fall zu sein, aber sicherlich muss es einen Weg geben, dies zu tun, da es den Code drastisch reduzieren würde, besonders dort, wo Teile von Abfragen häufig wiederverwendet werden.

+0

Haben Sie versucht, in-Auskleiden der 'GetRootDomainsForArticle' Abfrage in Ihre Hauptabfrage. Auch [dieses SO] (https://stackoverflow.com/questions/1230551/comparison-operators-not-supported-for-type-system-linq-iqueryable1system-int) kann Ihnen helfen. –

+0

@SivaGopal das hat tatsächlich funktioniert! Die Frage ist warum? Die Daten, die von der GetRootDomainsForArticle-Methode stammen, möchte ich für andere Methoden wiederverwenden. Daher würde ich gerne verstehen, warum das nicht funktioniert. – Jacques

+0

Mein Verständnis ist aufgrund der verzögerten Ausführung, Ihre Datenbank ist nicht bewusst, welche Funktion versuchen Sie anzurufen, nicht wahr? –

Antwort

0

Versuchen Sie, Ihre Funktion mehr aufzuteilen, die lange und tiefe Linq-Methode kann funktionieren, aber es ist nicht so gut für Lesbarkeitszwecke und kann diese Art von Fehlern einführen, über die Sie sprechen. Ich habe dies noch nicht getestet, aber es sollte Ihr Problem lösen helfen:

public List<DTO.ArticleDTO> GetRecentArticles(int portalID, int moduleID, int domainID, int rootKnowledgeTypeID, int count) 
{ 
    var allArticles = _Context.Articles.LatestArticles(_Context.ArticleVersions, portalID, moduleID); 
    var filteredArticles = new List<DTO.ArticleDTO>(); 

    foreach (DTO.ArticleDTO article in allArticles) 
    { 
     var domains = _GetRootDomainsForArticle(article.ArticleID, article.Version, rootKnowledgeTypeID); 
     if (domains.Contains(domainID) 
     { 
      filteredArticles.Add(article); 
     } 
    } 

    var articles = filteredArticles.OrderBy(article.UpdatedOn).Descending().Select(article => new DTO.ArticleDTO { 
     ArticleID = article.ArticleID, 
     Title = article.Title, 
     Summary = article.Introduction, 
     Content = article.Content, 
     UpdatedOn = article.UpdatedOn, 
     Version = article.Version, 
     KnowledgeTypeText = (from category in _Context.Categories 
              join categoryVersion in _Context.ArticleCategoryVersions 
              on category.CategoryID equals categoryVersion.CategoryID 
              where 
              categoryVersion.Version == article.Version && 
              categoryVersion.ArticleID == article.ArticleID && 
              category.ParentID == rootKnowledgeTypeID 
              select 
              category.Name 
             ).First() 
    }).Take(count).ToList(); 
} 

Auch haben Sie unbedingt benötigen zurückzukehren IQueryable <> von Ihrem _GetRootDomainsForArticle Funktion? Wenn Sie damit durchkommen, würde ich versuchen, IEnumerable <> stattdessen zurückgeben.

Koda

+0

Entpacken Sie nicht zuerst die gesamte Liste aus der Datenbank und filtern dann? Dies könnte möglicherweise Tausende von Artikeln sein, die Sie dann über den Draht bewegen müssen, bevor Sie sie filtern? – Jacques

+0

Der Punkt ist, das Problem zu diagnostizieren, während Ihre Logik in einer mehrstufigen linq-Abfrage verpackt ist, wird es immer schwieriger, Probleme zu lösen, wie Sie konfrontiert sind. Machen Sie Code, der zuerst funktioniert, dann optimieren Sie wie Sie tun, damit Sie nicht mehr Ressourcen als nötig verwenden. – Kodaloid

+0

vollständig verstehen Sie Ihren Punkt, ich habe diese Abfrage an anderer Stelle ausgeführt, ohne die Where-Klausel Aufruf der _GetRootDomainsForArticle und es funktioniert. _GetRootDomainsFOrArticle funktioniert von selbst und wird auch anderswo verwendet, in einer ähnlichen Weise wie Sie es vorschlagen, aber wo ich nur eine Handvoll von Artikeln extrahiere, so ist der Verkehr über den Draht nicht allzu wichtig – Jacques

Verwandte Themen