【问题标题】:Linq query results in Comparison operators not supported for type 'System.Linq.IQueryable`1[System.Int32]Linq 查询导致类型“System.Linq.IQueryable”1[System.Int32] 不支持比较运算符
【发布时间】:2018-02-17 02:29:43
【问题描述】:

我有以下功能:

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]'不支持比较运算符。”

我认为是因为延迟执行,但我不太明白正确的做法。

编辑:

根据@SivaGopal 评论,我将查询从 _GetRootDomainsForArticle 移到了主查询的一部分,并且它起作用了:

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 的有限理解使我相信可以将该查询拆分为一种方法作为查询组合的形式,从而使其可重用。似乎并非如此,但肯定有一种方法可以做到这一点,因为它会大大减少代码,尤其是在查询部分经常被重用的情况下。

【问题讨论】:

  • 您是否尝试将GetRootDomainsForArticle 查询内嵌到您的主查询中。 this SO 也可以帮助你。
  • @SivaGopal 确实有效!问题是为什么?来自 GetRootDomainsForArticle 方法的数据是我想为其他方法重用的数据,所以我真的很想了解它为什么不起作用。
  • 我的理解是由于延迟执行,你的数据库不知道你要调用什么函数,不是吗?
  • @SivaGopal 我对 Linq 还比较陌生,所以仍然要掌握它,但我认为 _GetRootDomainsForArticle 正在返回 IQueryable,所以我理解它是一种查询组合形式。
  • This SO 可以让您更深入地了解我所说的内容。

标签: c# linq linq-to-sql contains


【解决方案1】:

尝试更多地拆分你的函数,长而深的 Linq 方法可以工作,但它对可读性的目的不是那么好,并且可能会引入你所说的这类错误。我尚未对此进行测试,但它应该有助于解决您的问题:

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

你也绝对需要从你的 _GetRootDomainsForArticle 函数中返回 IQueryable 吗?如果你能侥幸成功,我会尝试返回 IEnumerable。

柯达

【讨论】:

  • 你不是这样先从数据库中提取整个列表然后过滤吗?这可能是数以千计的文章,然后您需要在过滤它们之前通过网络移动它们?
  • 重点是诊断问题,虽然您的逻辑包含在多级 linq 查询中,但解决您面临的问题总是会更加困难。先编写可以运行的代码,然后像您正在做的那样进行优化,这样您就不会使用比需要更多的资源。
  • 完全理解您的意思,我在其他地方运行该查询,而没有调用 _GetRootDomainsForArticle 的 where 子句,它可以工作。 _GetRootDomainsFOrArticle 自行运行,并且在其他地方也以与您建议的方式有些相似的方式使用,但我只提取少数文章,因此网络上的流量不是太大的问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多