我最近一直在研究我的 Web 应用程序性能,发现了一些 LINQ 查询,我不确定更改它们是否会提高性能。
基本上当前的代码如下所示:
var result = _carsRepository.GetAll()
.Where(x => x.Name == input.Name)
.FirstOrDefault();
if (result != null)
{
throw new Exception("test");
}
我正在考虑将其更改为:
var result = _carsRepository.GetAll()
.Where(x => x.Name == input.Name)
.Any();
if (result)
{
throw new Exception("test");
}
根据我的理解,第一个查询将返回一个实际的实体,我不需要它,因为我只想知道数据库中是否已存在同名的记录。第二个查询只返回一个布尔值。
我将不胜感激任何评论。
编辑:我可以在EF db上下文上运行查询,所以请忽略它。 当前存储库是一个通用的 Abp.Domian.Repository。 GetAll(( 返回 IQueryable
我不确定GetAll()
做什么。如果它将所有项目从您的数据库移动到您的本地内存,那么我不会打扰:尝试改进该语句。如果您只需要第一个项目,为什么要获取所有项目。
如果GetAll()
返回一个IQueryable<...>
,则略有不同:
FirstOrDefault()
将更改查询中的表达式,以便 SQL 语句Select top 1 ... from
。
更改表达式后,它将要求IQqueryable
的Provider
执行Expression
,SQL语句的完整结果将b传输到本地内存,在这种情况下将是一个项目。
Any()
几乎会做同样的事情,除了SQL将是:Select top 1 1 from ...
很容易看出,Select top 1 1
最多会传输一个整数,而Select top 1
将传输所有选定的列。
因此,如果您只想检查是否有任何元素,Any()
比FirstOrDefault
更有效
我们无法告诉您,因为我们既不知道您的存储库类是做什么的,也不知道您的数据库驱动程序如何处理到 SQL 的转换。
测试两者,对它们进行基准测试,查看 SQL,并检查您的数据库分析工具是否可能错过索引或其他优化机会。
仅从Linq就无法分辨。
可能会有细微的差异,因为
.FirstOrDefault()
- 读取所有列
.Any()
- 只需检查是否有条目
差异将主要基于数据大小和SQL结构,索引和所有。建议通过测试对它们进行基准测试
No.您可能不会获得任何性能差异。因为
1(Any((将在找到匹配项后立即返回。
2(FirstOrDefault(( 迭代(可能(在找到满足条件的元素时停止。
LINQ to objects:Enumerable.Any 和Enumerable.FirstOrDefault应执行相同的操作,因为它们的代码几乎相同:
优先或默认:
foreach (TSource source1 in source)
{
if (predicate(source1))
return source1;
}
return default (TSource);
任何:
foreach (TSource source1 in source)
{
if (predicate(source1))
return true
}
return false;
现在。看起来您正在从内存中的数据库中获取所有记录,然后应用 where 子句。
尽量避免在内存中一次加载数据。然后它会给你性能差异
如前所述,目前还不清楚您的存储库是做什么的。但是,如果您遵循存储库模式,则应考虑将 Any 添加为存储库中的方法。
public virtual bool Any(Expression<Func<T, bool>> predicate)
{
return _context.Set<T>().Any(predicate);
}
这将确保您的 Any 在数据库上执行,因为此方法将 Any 作为 IQueryable 执行。
如果您没有在存储库中使用泛型,则将 T 替换为目标类。