简体   繁体   中英

Linq query results in Comparison operators not supported for type 'System.Linq.IQueryable`1[System.Int32]

I have the following function:

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

What I'm trying to do is get all the articles that belong to a root category (domain ID). Categories are considered to be Domains/SubDomains and each article can belong to one or more Domains and Sub Domains. So this is why I used the following method in the where clause of the above linq query.

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

The error I get is: "Comparison operators not supported for type 'System.Linq.IQueryable`1[System.Int32]'."

I think is is because of deferred execution, but I don't quite understand the right way to do it.

Edit:

Based on @SivaGopal comment I moved the query from the _GetRootDomainsForArticle to become part of the main query and it worked:

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

My limited understanding of Linq lead me to believe that one could split that query out to a method as form of query composition and in so doing making it reusable. Seems not to be the case, but surely there must be a way to do this as it would drastically reduce code especially where portions of queries are reused quite often.

Try splitting up your function more, the long and deep Linq method can work, but it is not that good for readability purposes and can introduce these sort of bugs that you are talking about. I haven't tested this yet but it should help solve your issue:

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

Also do you absolutely need to return IQueryable<> from your _GetRootDomainsForArticle function? If you can get away with it, I'd try returning IEnumerable<> instead.

Koda

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM