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

时间:2013-01-24 19:51:51

标签: c# linq

我想知道我是否做了类似的事情:

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

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

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

结果永远不会为NULL ...

谢谢。

5 个答案:

答案 0 :(得分:6)

既然你只是想知道获得完整的结果集是否值得,那就永远不值得了。

这里只有两种情况:

  1. 您的查询没有结果。在这种情况下,检查有多少结果的查询将花费与执行一样长的时间,并返回与 real 查询一样多的信息。在这种情况下,你什么也得不到(但也没有失去任何东西)。

  2. 您的查询至少有一个结果。在这种情况下,您需要返回并执行真实查询。最终的结果是你花了尽可能多的时间没有先检查,但是你还要增加检查是否有结果的费用。该检查意味着往返数据库,这是一个非常重要的时间。

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

    同样值得注意的是,正如lazyberezovsky在his answer中所做的那样,您还需要考虑在您致电Any后查询结果发生变化的竞争条件。

答案 1 :(得分:3)

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

样品:

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

之类的内容加载数据

答案 2 :(得分:1)

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

results.Any();

根据MSDN:

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

MSDN ANY

答案 3 :(得分:0)

感谢您提供有用的建议和精确度。我最终在我的通用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的复杂类类型,所以似乎没问题。

答案 4 :(得分:-2)

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

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