在调用 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() 懒惰地执行。
返回的数据集可能很大,调用上述方法非常耗时。
结果也永远不会为空...
谢谢。
由于您只是想知道是否值得获得完整的结果集,因此永远不值得这样做。
这里只有两种情况:
-
您的查询没有结果。 在这种情况下,用于检查有多少结果的查询将花费与实际查询相同的时间来执行,并返回与实际查询完全相同的信息。 在这种情况下,你什么也得不到(但也一无所获)。
-
您的查询至少有一个结果。 在这种情况下,您需要返回并执行实际查询。 最终结果是,您花费的时间与不先检查的时间一样多,但您还需要增加检查是否有结果的成本。 该检查意味着往返数据库,这是一个不平凡的时间。
如果您想知道查询是否包含任何项目,这是可能的。 (只需使用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) 执行