2017-09-08 6 views
0

나는 다음과 같은 기능이 있습니다 :LINQ 쿼리 결과 '유형에 대해 지원되지 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(); 
} 

난 할 노력하고있어 얻을 수있는 모든 루트 카테고리 (도메인 ID)에 속하는 기사. 카테고리는 도메인/하위 도메인으로 간주되며 각 아티클은 하나 이상의 도메인 및 하위 도메인에 속할 수 있습니다. 그래서 위의 linq 쿼리의 where 절에서 다음 메서드를 사용했습니다.

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; 
} 

내가 오류입니다 "비교 연산자가 '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 (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(); 
} 

Linq에 내 제한된 이해가 나를 인도 : I 메인 쿼리의 일부가되기 위해 _GetRootDomainsForArticle에서 쿼리를 이동하고 일 @SivaGopal 의견을 바탕으로

그 쿼리를 쿼리 컴포지션의 형태로 메서드에 분할 할 수 있고 재사용 가능하게 만들 수 있다고 믿습니다. 그렇지 않은 것 같지만 분명히 쿼리의 부분이 꽤 자주 재사용되는 곳에서 코드를 대폭 줄일 수있는 방법이 있어야합니다.

+0

기본 쿼리에'GetRootDomainsForArticle' 쿼리를 시도 했습니까? 또한 [this so] (https://stackoverflow.com/questions/1230551/comparison-operators-not-support-for-type-system-linq-iqueryable1system-int)가 도움이 될 수 있습니다. –

+0

실제로 작동 한 @SivaGopal! 그 이유는 무엇입니까? GetRootDomainsForArticle 메서드에서 오는 데이터는 다른 메서드에 대해 재사용하고 싶습니다. 그래서 실제로 작동하지 않는 이유를 이해하고 싶습니다. – Jacques

+0

필자의 이해는 지연된 실행으로 인한 것이며 데이터베이스는 어떤 기능을 호출하려고하는지 알지 못합니다. –

답변

0

더 많은 기능을 나누어보십시오. 길고 깊은 Linq 방법이 효과적 일 수 있지만 가독성을 위해 좋지는 않으며 이러한 유형의 버그를 소개 할 수 있습니다. 나는 아직 테스트하지 않은 있지만, 문제 해결 도움이 될 것입니다 또한 당신이 절대적으로 당신의 _GetRootDomainsForArticle 함수에서 된 IQueryable <>를 반환해야합니까

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(); 
} 

를? 그걸로 도망 갈 수 있다면 IEnumerable <>을 대신 반환 해 보겠습니다.

코다

+0

먼저 데이터베이스에서 전체 목록을 추출한 다음 필터링하지 않습니까? 이것은 잠재적으로 기사를 필터링하기 전에 전선을 가로 질러 이동해야하는 수천 개의 기사 일 수 있습니다. – Jacques

+0

요점은 문제를 진단하는 것입니다. 논리가 다단계 linq 쿼리로 마무리되면 항상 직면하는 문제를 해결하는 것이 더 어려워 질 것입니다. 먼저 작동하는 코드를 만든 다음 필요에 따라 더 많은 리소스를 사용하지 않도록 최적화하십시오. – Kodaloid

+0

완전히 귀하의 요점을 이해, 그 쿼리는 _GetRootDomainsForArticle를 호출 where 절없이 다른 곳에서 실행하고 그것을 작동합니다. _GetRootDomainsFOrArticle 자체가 작동하며 다른 곳에서도 마찬가지로 사용하고 있습니다.하지만 기사의 일부만 추출하면 전선을 가로 지르는 트래픽이 너무 걱정되지 않습니다. – Jacques