【问题标题】:How to get total results count before .Take() - but when using .Take()如何在 .Take() 之前获得总结果计数 - 但在使用 .Take() 时
【发布时间】:2023-04-02 08:20:01
【问题描述】:

我正在使用 .Take() 来获得固定数量的结果。

获得TotalCountBeforeTake 的最佳方法是什么(即好像我没有使用.Take())?

我可以在不运行两次查询的情况下获得TotalCountBeforeTake 吗?

        var Results = (from results in db.FindWords(term)
                       orderby results.word
                       select results.word).Take(100);

        //just to get the total record count
        int TotalCountBeforeTake = (from results in db.FindWords(term)
                            select results.word).Count();

        // only showing 100 out of TotalCountBeforeTake results,
        // but in order to know the TotalCountBeforeTake I had to run the query twice.
        foreach (var result in Results)
        {
            Console.Write(result.ToString());
        }

【问题讨论】:

  • 做到这一点的最佳方法实际上取决于有问题的IEnumerable。如果由数据库支持,那么执行多个查询会更快。如果是 Linq to Objects,那么编写一个 while 循环可能会更快。
  • 哦,我会考虑到的,它是 db drivem
  • 说到IEnumerable<T>,请确保您从db.FindWords(term) 得到的是IQueryable<T>

标签: c# linq take


【解决方案1】:

IEnumerables 和 LINQ 用于创建选择链。在你真正开始迭代之前,什么都没有被执行(除了创建选择链)。

这似乎很神奇,因为它极大地提高了性能,因为尝试使用列表实现相同的效果需要对列表进行多次迭代。

但是,当您不止一次地开始迭代一个可枚举对象时,您就是在购买具有多个操作的 LINQ 的优雅,这会将您的性能优势降低到零或以下。

换句话说:将您的 linq 表达式转换为数组并继续。

 var Results = (from results in db.FindWords(term)
                     orderby results.word
                     select results.word).Take(100).ToArray();

现在您可以计数、迭代而不会损失性能。

【讨论】:

  • 这并没有给出在取 100 之前的计数 - 除非它的工作方式与我认为的不同
  • 不,这不起作用。计算数组每次只会告诉您“100”或更少——而不是查询将返回的项目总数。
【解决方案2】:

您想查询两件事 - 项目的总数和项目的子集。所以你需要运行两个查询:

    // Define queries
    var query1 = from results in db.FindWords(term)
                 orderby results.word
                 select results.word;

    var query2 = query1.Take(100);

    // Run queries
    int totalCountBeforeTake = query1.Count();

    foreach (var result in query2)
    {
        Console.Write(result.ToString());
    }

【讨论】:

  • 哦,我以为我试过了,但没用,我一定是在尝试时犯了一个愚蠢的错误!谢谢。
  • 这个答案确实是优化的。考虑一个有一百万字的数据库表。它会首先COUNT(*) 他们,然后是SELECT TOP 100 ... 他们。比读取一百万个单词并将它们存储在列表中要快得多。
【解决方案3】:

我不知道如何在不拆分的情况下获得计数(希望其他人这样做),但在您的情况下,我建议:

//first get the records
var query = (from results in db.FindWords(term)
                       orderby results.word
                       select results.word).ToList();

//get the total record count
int TotalCountBeforeTake = query.Count();

// only showing 100 out of results,
foreach (var result in query.Take(100))
{
    Console.Write(result.ToString());
}

【讨论】:

  • 我认为这可能是更好的解决方案,即获取一次但枚举两次。我很想看看是否有人有更好的。谢谢
  • 请注意,如果项目总数很高,与运行两个查询相比,这种方法会非常慢,因为它必须将每个项目完全加载到内存中。
  • @dtb 我几乎提出了与您的查询基本相同的查询......与这些事情一样,查询与枚举的相对成本是平衡的事情......如果那个 db. FindWords(term) 是针对没有全文索引的表的文本搜索,与廉价的枚举相比,您可以想象得到非常昂贵的查询。用棍子戳它,看看会发生什么:-)
猜你喜欢
  • 2016-02-09
  • 1970-01-01
  • 2017-03-29
  • 1970-01-01
  • 1970-01-01
  • 2019-01-12
  • 2015-04-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多