在调用 ToList() 或 Count() 之前检查 LINQ Where() 是否返回了任何内容

本文关键字:是否 Where 返回 LINQ 任何内 ToList 调用 Count 检查 | 更新日期: 2023-09-27 17:56:07

我想知道我是否做这样的事情:

var results = source.Where(c => c.Name == "Whatever");

有没有办法在调用 Count() 或 ToList() 之前检查查询是否返回了任何内容?我知道 Where() 懒惰地执行。

返回的数据集可能很大,调用上述方法非常耗时。

结果也永远不会为空...

谢谢。

在调用 ToList() 或 Count() 之前检查 LINQ Where() 是否返回了任何内容

由于您只是想知道是否值得获得完整的结果集,因此永远不值得这样做。

这里只有两种情况:

  1. 您的查询没有结果。 在这种情况下,用于检查有多少结果的查询将花费与实际查询相同的时间来执行,并返回与实际查询完全相同的信息。 在这种情况下,你什么也得不到(但也一无所获)。

  2. 您的查询至少有一个结果。 在这种情况下,您需要返回并执行实际查询。 最终结果是,您花费的时间与不先检查的时间一样多,但您还需要增加检查是否有结果的成本。 该检查意味着往返数据库,这是一个不平凡的时间。

如果您想知道查询是否包含任何项目,这是可能的。 (只需使用Any扩展方法。 但是,仅当您不需要知道实际项目是什么时,无论Any的结果如何,它才有用

还值得注意的是,正如 lazyberezovsky 在他的回答中所做的那样,您还需要考虑在调用 Any 后查询结果发生变化的竞争条件。

知道查询是否会返回某些内容的唯一方法是执行该查询。因此,您可以获得结果或检查结果计数/存在。在第二种情况下,您无法确定进一步执行查询是否会产生相同的结果。

样本:

List<int> items = new List<int>() { 1, 2, 3 };
var query = items.Where(i => i > 0);
// query is not executed at this point
var count = query.Count(); // first execution, returns 3
items.Clear();
var positiveItmes = query.ToList(); // ooop, no items here!

因此,如果您确定数据不会在查询之间更改(您是完全吗?),则可以在获取所有数据之前使用Count()Any()。在其他情况下,您必须使用类似 ToList() .

当然,只需使用任何它会告诉您是否有任何结果。

results.Any();

根据 MSDN:

此方法不返回集合的任何一个元素。相反,它确定集合是否包含任何元素。一旦可以确定结果,源的枚举就会停止。

MSDN ANY

感谢您的有用建议和精度。我最终在我的通用 EF 存储库中实现了这一点:

    public bool CheckExists(string tableName, string whereField, string whereValue)
    {
        string query = string.Format("SELECT COUNT(*) FROM {0} WHERE {1} = {2}", tableName, whereField, whereValue);
        var count = _context.ExecuteStoreQuery<int>(query).FirstOrDefault();
        if (count == 0)
            return false;
        else
            return true;
    }

快多了!:)我仍在执行查询,但由于我没有要求 LINQ/EF 将潜在结果转换为复杂类类型的 IENumerable,因此似乎还可以。

var any = (source.Where(c => c.Name == "Whatever").FirstOrDefault() != null);

FirstOrDefault 将作为 SELECT TOP 1 (LinqToSql) 执行